ObjC中定义属性时的atomic、nonatomic、copy、assign、strong、weak几个特性的区别

iOS编程中,定义属性中的特性有atomic、nonatomic、copy、assign、strong、weak、getter、nullable等,一般格式如下:

@property (nonatomic, strong) NSString *name; 

下面详细解释一下他们的区别。

atomic

  • 默认属性。
  • 当前进程进行到一半,其他线程来访问当前线程,可以保证先执行完毕当前线程。
  • 只是保证setter/getter 完整,不是线程安全。

例如:对于atomic的对象,线程A调用getter,同时线程B、线程C都调用setter并设不同的值,最后线程A可能得到原来的值、也可能得到线程B、线程C设的值,只能够保证得到的是原始值、B线程设定的值、C线程设定的值三者中一个完整值,没有办法确定最终得到的是哪个值。如果线程D调用release,程序会崩溃。所以atomic只是read/write安全,不是thread安全。

nonatomic

  • 非默认属性。
  • 两个线程同时访问同一个属性将会导致无法预计的结果。
  • 优点是程序运行速度快。

 

atomic和nonatomic的对比

1、atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。

2、atomic:系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。getter 还是能得到一个完好无损的对象(可以保证数据的完整性),但这个对象在多线程的情况下是不能确定的,比如上面的例子。

也就是说:如果有多个线程同时调用setter的话,不会出现某一个线程执行完setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁一样,每次只能有一个线程调用对象的setter方法,所以可以保证数据的完整性。

atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。

3、nonatomic:就没有这个保证了,nonatomic返回你的对象可能就不是完整的value。因此,在多线程的环境下原子操作是非常必要的,否则有可能会引起错误的结果。但仅仅使用atomic并不会使得对象线程安全,我们还要为对象线程添加lock来确保线程的安全。

4、nonatomic的速度要比atomic的快。

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

 

copy

  • 是owner,不是reference(引用)。当对象可变时,可设置为copy,用于获取此时值的副本。
  • 新的对象引用计数为1,与原始对象引用计数无关,且原始对象引用计数不会改变。
  • 使用copy创建的新对象也是强引用,使用完成后需要负责释放该对象。
  • copy特性可以减少对象对上下文的依赖。新对象、原始对象中任一对象的值改变不会影响另一对象的值。
  • 要想设置该对象的特性为copy,该对象必须遵守NSCopying协议,Foundation类默认实现了NSCopying协议,所以只需要为自定义的类实现该协议即可。更全面了解NSCopying协议,查看 深复制、浅复制、copy、mutableCopy一文。

assign

  • 与copy相反,只是reference,不是owner。只返回指针。
  • 用于float、int、BOOL等类型。
  • 释放后再发送消息会导致程序崩溃。

strong

  • 默认属性
  • strong = retain iOS引入ARC后,用strong替代了retain。
  • 创建一个强引用的指针,引用对象引用计数加1。
  • strong特性表示两个对象内存地址相同(建立一个指针,进行指针拷贝),内容会一直保持相同,直到更改一方内存地址,或将其设置为nil
  • 如果有多个对象同时引用一个属性,任一对象对该属性的修改都会影响其他对象获取的值。
  • 所有实例变量、局部变量默认都是strong。

weak

  • 只是reference,不是owner。即引用计数不会加1。
  • 可将weak对象设为nil,向nil发送消息,什么都不会执行,程序也不会崩溃。
  • 代理使用weak。delegate几乎一直own代理对象,所以代理对象应该对代理使用weak,否则会形成循环引用(retain cycle)。但也有例外,如果代理对象的生命周期比代理短,代理对象也可以使用strong。
  • IBOutlet常用weak。
  • 10.8之前的OSX系统,使用unsafe_unretained替代

关于strong和weak对比的一个形象例子

假设对象是一条小狗,小狗想跑走(be deallocated)。

strong类型就像是拴狗的绳子,只要有一条绳子栓住狗,它就不能跑走,如果有五条绳子拴着同一条狗(五个strong类型指向同一个对象),只有当五条绳子都释放狗才可以跑走。

weak类型就像是小孩子看着小狗说:看这里有小狗。只要还有绳子拴着小狗,小孩子们就可以继续指着小狗说:看这里有小狗。当绳子释放了的时候,不管有多少小孩子依旧在指着小狗说:看这里的小狗。小狗都会跑掉。

当最后一个strong指针不再指向这个对象,这个对象就会被释放,此时,所有指向这个对象的weak指针都将被清空。

readonly

  • 非默认属性
  • 只有可读方法,也就是只有getter方法。

readwrite

  • 默认属性
  • 如果希望一个属性只允许自己读写,而对所有外部文件都是只读的,可以在接口部分声明该属性为readonly类型,最后在私有接口部分重写该属性为readwrite类型。

nullable

不可为null,不能为nil

@property (readonly, getter = isOpen) BOOL open

特殊指定getter方法,getter相对应的是setter,对变量的实现或访问方法重定义。

 

更多:https://github.com/pro648/tips/wiki

链接:https://www.jianshu.com/p/66b77270e363

链接:https://www.jianshu.com/p/4fb51144d4ca
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

 


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值