在 iOS 开发中经常会用到 copy 关键字,主要的应用方面就是 @property 属性的修饰。这篇文章主要关心:
数组(NSArray、NSMutableArray)与 copy
NSMutableArray 作为属性该使用 strong 还是 copy 修饰?
1 |
|
比如,这里有个 Person 类,有一个属性是 catNames,用于存放猫的名字, 我们使用:
1 | Person *p = [Person new]; |
这段程序运行的结果是:
1 | 2018-07-24 12:51:11.928550+0800 CopyDemo[5781:3493921] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArray0 addObject:]: unrecognized selector sent to instance 0x60400000cdc0' |
crash 了!!!
为什么会 Crash 呢?
首先,crash 的语言是找不到方法(unrecognized selector sent to instance)。
其次,我们通过 @property (nonatomic, copy) NSMutableArray *catNames;
做了什么,是让系统自动为我们生成了 setter 和 getter 方法,而 copy 就控制着这些方法的生成细节。如果不修改这段声明的话,可以在 Person 的实现中修改 setter 方法的实现:
1 | - (void)setCats:(NSMutableArray *)cats { |
或者
1 | - (void)setCats:(NSMutableArray *)cats { |
本质就是:一个 NSMutableArray 的对象,经过 copy 方法生成对象其实是一个 NSArray 对象,也就是上面 p.cats = [NSMutableArray arrayWithCapacity:10];
赋值运算符左侧其实是一个不可变数组了,而右侧是可变数组。
综上,针对于可变数组,我们使用 strong 来进行修饰,不用 copy。
NSArray 作为属性该使用 strong 还是 copy 修饰?
上面已经说明了,针对 NSMutableArray 我们使用 strong 来进行修饰,那么 NSArray 呢?
首先,我们来看一下,使用 strong
来修饰,会怎样?
1 |
|
为 Person 类添加了属性 phones,标识当前人对象拥有的手机,从 API 的定义可以看出,是不可变数组,所以当我们为这个人对象设置了 phones 属性之后,我们不希望手机数量会发生变化,接下来看是具体使用:
1 | - (void)addPhones { |
从上面可以看出,如果我们通过 strong 来进行修饰的话,就不能空着 NSArray 的不可变性了,所以对于 NSArray 我们使用 copy 来修饰会更好一些,这样可以保证类属性的封装性。