一.首先@property的关键字分三类
-
一类是表示原子性(也就是线程安全)的,有atomic和nonatomic,默认是atomic,atomic是线程安全的,cpu会保证其他线程访问该属性之前先执行完当前流程,但是我们一般都用的nonatomic,因为atomic的线程安全开销太大,影响性能,即使需要保证线程安全,我们也可以通过自己的代码控制,而不用atomic。
-
一类是表示引用计数的,有assign,strong,weak,copy,return。
-
一类是表示读写权限的,默认是readwrite(可读可写),还有就是readonly(可读)。
日常工作中copy和strong是使用频率非常多的关键词,也是本文重点要研究的内容。
二.strong与copy关键词分析
strong修饰的属性会对指向的对象进行强引用,大部分属性都需要用strong。
这里有一个被问过很多的问题
- xib中的视图拖线到控制器中为什么是用weak修饰的?
- 原因在于IBOutlet的属性已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。
NSString、NSArray、NSDictionary 等经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary。为确保对象中的属性值不会无意间变动,应该在设置新属性值时拷贝一份。对于 block 使用 copy 还是 strong 效果是一样的,但是建议写上 copy,因为这样显示告知调用者编译器会自动对 block 进行了 copy 操作。
接下来看两行代码:
@property (nonatomic, strong) NSArray *array;
@property (nonatomic, copy) NSMutableArray *mutableArray;
从上面的解释中基本可以分析出导致的问题,首先第一行代码
@property (nonatomic, strong) NSArray *array;
在大多数情况下貌似都没有问题,但是当出现以下场景时:
NSMutableArray *mutaArray = [NSMutableArray array];
self.array = mutaArray;
[mutaArray addObject:@"1"];
可以发现我们只是想修改mutaArray这个数组,然而self.array也跟着改变了,这往往可能导致一些莫名其妙,匪夷所思的问题。。
接下来继续看第二行代码:
@property (nonatomic, copy) NSMutableArray *mutableArray;
这行代码在一些情况下会发生Crash,例如:
NSMutableArray *mutaArray = [NSMutableArray array];
self.mutaArray = mutaArray;
[self.mutaArray removeAllObjects];
原因在于 self.mutaArray = [mutaArray copy] 之后变成了不可变数组,如果用strong修饰就不会有这个问题,因为直接是赋值,右边是什么,左边就是什么,并且是强引用新值,左边的类型会与右边的相同,不会改变。
最后总结:
NSString、NSArray、NSDictionary 等经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary。而NSMutableString、NSMutableArray、NSMutableDictionary 则往往使用 strong 关键字更为妥当。