美文网首页selector
@property中的关键字:weak,assign,atomi

@property中的关键字:weak,assign,atomi

作者: CyberDunk1997 | 来源:发表于2020-10-05 20:49 被阅读0次

    @property中的关键字:https://www.jianshu.com/p/3709cf8f8937
    成员变量和属性的区别:https://www.jianshu.com/p/16692335eb41

    1. @property做了些什么?

    当我们写下property NSObject *foo;时,编译器为我们做了三件事

    • 创建实例变量_foo
    • 声明foo属性的setter和getter方法
    • 实现foo属性的setter和getter方法
    @property的本质是什么?

    @property = ivar(实例变量) + getter(get方法) + setter(set方法);

    也就是说使用@property 系统会自动生成setter和getter方法;

    2. atomic和nonatomic

    • atomic和nonatomic会决定编译器生成的setter和getter方法是否为原子操作,即会保证setter和getter的完整性。如果有多个线程同时调用setter的话,相当于函数头尾加了锁一样,每次只能有一个线程调用对象的setter方法,所以可以保证数据的完整性。
    • 被atomic修饰的属性任何线程对其访问,都能获得一个完整初始化后的对象,用nonatomic修饰则不一定能保证。
    • 因为要保证完整性,所以atomic比nonatomic要慢。
    • atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。
    举例:

    如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,有3种 可能:可能是 B、C set 之前原始的值,也可能是 B set 的值,也可能是 C set 的值。同时,最终这个属性 的值,可能是 B set 的值,也有可能是 C set 的值。所以atomic可并不能保证对象的线程安全。

    • atomic与nonatomic的本质区别其实也就是在setter方法上的操作不同

    • atomic 修饰的对象,系统会保证在其自动生成的 getter/setter 方法中的操作是完整的,不受其他线程的影响。例如 A 线程在执行 getter 方法时,B线程执行了 setter 方法,此时 A 线程依然会得到一个完整无损的对象。

    总结:

    atomic
    • 默认修饰符
    • 会保证CPU能在别的线程访问这个属性之前先执行完当前操作
    • 读写速度慢
    • 线程不安全 - 如果有另一个线程 D 同时在调[name release],那可能就会crash,因为 release 不受 getter/setter 操作的限制。也就是说,这个属性只能说是读/写安全的,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。
    nonatomic
    • 不默认
    • 速度更快
    • 线程不安全
    • 如果两个线程同时访问会出现不可预料的结果。

    3.assign

    • 这个关键字一般用在基本数据类型,比如如NSInteger和CGFloat等,如果不用其他关键词修饰,默认用assign
    • assign也可以用来修饰对象,但是对象的计数不会+1
    • 如果assign用来修饰对象,当对象被销毁后指针不会指向nil,所以会出现野指针。如果assign用来修饰基本数据类型则不会发生这种情况,因为基本数据类型被存储在栈上管理,栈内存会被自动回收,所以一般用assign修饰基本数据类型

    4. weak

    • weak一般用来修饰OC对象,表示指向但不拥有该对象,不会使对象的引用计数+1,当该对象被释放时,会自动设置为nil。

    weak的原理

    • Runtime中维护了一个weak表(hash表),用于存储某个对象的所有weak指针。在这个表中,key是所指对象的地址,value是一个数组,里面装的是weak指针的地址(因为一个对象可能被多个弱引用指针指向)。

    weak的实现步骤

    NSObject *obj = [[NSObject alloc] init];
    id __weak obj1 = obj;
    

    当weak修饰的对象被释放时,weak指针的处理流程

    1. 调用objc_release
    2. 因为对象的引用计数为0,所以执行dealloc
    3. 在dealloc中,调用了 _objc_rootDealloc函数 -> 调用了object_dispose函数 -> 调用objc_destructInstance -> 最后调用objc_clear_deallocating
    4. objc _ clear _ deallocating该函数的动作如下:
      1. 从weak表中获取废弃对象的地址为键值的记录
      2. 将包含在记录中的所有附有 weak修饰符变量的地址,赋值为nil
      3. 将weak表中该记录删除
      4. 从引用计数表中删除废弃对象的地址为键值的记录

    5. copy

    小结iOS中的copy:https://www.jianshu.com/p/5254f1277dba

    预备知识

    • 浅拷贝 :只是将对象内存地址多了一个引用,也就是说,拷贝结束之后,两个对象的值不仅相同,而且对象所指的内存地址都是一样的。
    • 深拷贝 :拷贝一个对象的具体内容,拷贝结束之后,两个对象的值虽然是相同的,但是指向的内存地址是不同的。两个对象之间也互不影响,互不干扰。
    • copy拷贝出来的对象类型总是不可变类型(例如, NSString, NSDictionary, NSArray等等),mutableCopy拷贝出来的对象类型总是可变类型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)

    copy的作用

    • copy与strong类似。不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰【有可变对应类型】的不可变对象上,如NSString, NSArray, NSDictionary。

    相关文章

      网友评论

        本文标题:@property中的关键字:weak,assign,atomi

        本文链接:https://www.haomeiwen.com/subject/dajauktx.html