property的关键字分三类:
1.原子性(也就是线程安全):atomic和nonatomic,默认是atomic,acomic会保证 CPU 能在别的线程来访问这个属性之前,先执行完当前流程,我们一般用nonatomic,因为atomic的线程安全开销太大。
- atomic 和 nonatomic 的区别在于,系统自动生成的 getter/setter 方法不一样。如果自己写 getter/setter方法,那 atomic/nonatomic/retain/assign/copy 这些关键字只起提示作用,写不写都一样。
- atomic的属性,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。比如,线程 A 的 getter 方法运行到一半,线程 B 调用了 setter:那么线程 A 的 getter 还是能得到一个完好无损的对象。
- nonatomic就没有这个保证了。所以,nonatomic的速度要比atomic快。
- 不过atomic可并不能保证线程安全。如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,3种都有可能:可能是 B、C set 之前原始的值,也可能是 B set 的值,也可能是 C set 的值。同时,最终这个属性的值,可能是 B set 的值,也有可能是 C set 的值。
- 保证数据完整性——这个多线程编程的最大挑战之一——往往还需要借助其他手段。
2.引用计数:assign(iOS5以前用unsafe_unretained)、strong、weak、copy,
- assign: assign用于非指针变量,一般用于基础类型和C数据类型,这些类型不是对象,统一由系统栈进行内存管理。
- weak:对对象的弱引用,不增加对象的引用计数,也不持有对象,当对象消失后指针自动指向nil,所以这里也就防止了野指针的存在。
- strong:对对象的强引用,会增加对象的引用计数,如果指向了一个空对象,会造成野指针,平常我们用得最多的应该也是strong了。
- copy:建立一个引用计数为1的新对象,赋值时对传入值进行一份拷贝,所以使用copy关键字的时候,你将一个对象赋值给该属性,该属性并不会持有那个对象,而是会创建一个新对象,并将那个对象的值拷贝给它,使用copy关键字的对象必须要实现NSCopying协议。
3.读写权限:readonly,readwrite
属性默认都是readwrite的,表示可读可写,set/get方法编译器都会自动合成。如果用readonly修成属性,表示该属性是只读的,编译器只会自动合成get方法, 不会合成set方法。另外,我们可以在.h文件中用readonly中修饰属性,在.m文件类扩展中用readwrite修饰同一个属性,这样来防止外界篡改该属性。