weak与assign
一、什么情况下使用 weak 关键字?
1、ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如:delegate 的代理属性。
2、自身已经对它有过一次强引用,所以没有必要再强引用一次。这个时候也会使用weak;还有就是自定义IBOutlet控件属性一般也使用weak,一般情况也可以使用strong。
二、weak和assign有什么不同?
1、weak的特质表明,该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值,但是weak修饰的对象被摧毁时,属性值也会清空(nil out)。assign的setter方法只会执行简单赋值操作。
2)assign可以用于非OC对象;weak必须用于OC对象,如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。MRC下,使用unsafe_unretained修饰对象类型。unsafe_unretained也可能产生野指针,所以它名字是"unsafe_”。
2.是否产生野指针的区别
weak 不会产生野指针问题。因为weak修饰的对象释放后(引用计数器值为0),指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。
assign 如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。
weak引用表原理:
https://www.cnblogs.com/doudouyoutang/p/9952026.html
https://www.cnblogs.com/yangwenhuan/p/9226689.html
http://yulingtianxia.com/blog/2015/12/06/The-Principle-of-Refenrence-Counting/
copy和strong
strong此特质标明该属性定义了一种拥有关系。为这种属性设定新值时,设置方法会先保留新值再释放旧值,然后再讲新值设置上去。
copy 此特质所表达的所属关系与strong类似。然而设置方法并不保留新值而是将其拷贝,当属性类型为NSString*时,经常用此特性来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例这个类是NSString的子类,表示一种可以修改其值得字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以这时就要拷贝一份不可变的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是可变的,就应该在设执行属性是拷贝一份
atomic和nonatomic
*atomic只是保证了getter/setter存取方法的线程安全.并不能保证整个对象是线程安全的,因此在多线程编程时,线程安全还需要开发者自己来处理。
*atomic系统生成的getter/setter会保证get/set操作的安全性,但相对nonatomic来说,atomic会更耗费资源,且速度要慢,故在iPhone等小型设备上,如果没有多线程之间的通讯,使用nonatomic是更好的选择。
此处可以引出锁的问题(锁用于解决线程争夺资源的问题,一般分为两种,自旋锁(spin)和互斥锁(mutex)):
iOS10之前atomic使用的是自旋锁,但是iOS 10之后,苹果因为一个巨大的缺陷弃用了 OSSpinLock 改为新的 os_unfair_lock。
新版 iOS 中,系统维护了 5 个不同的线程优先级/QoS: background,utility,default,user-initiated,user-interactive。高优先级线程始终会在低优先级线程前执行,一个线程不会受到比它更低优先级线程的干扰。这种线程调度算法会产生潜在的优先级反转问题,从而破坏了 spin lock。(描述引用自 ibireme 大神的文章:不再安全的 OSSpinLock)