面试中,常常会问到property中copy和strong修饰符的用法,要把简单的东西说透彻,还是需要花一些功夫的。在此,列举我在实际测试中使用这两个修饰符修饰数组或数据集及字符串获得的一些心得,以抛砖引玉。
例如常见的数组,有以下四种作为成员变量的写法:
@property (nonatomic, strong) NSArray * arr1; @property (nonatomic, strong) NSMutableArray * mutArr2; @property(nonatomic,copy)NSArray * arr3; @property(nonatomic,copy)NSMutableArray * mutArr4;
那么,这四种写法的区别究竟是什么呢?我针对这四种做了测试
1.strong修饰的NSArray:
@property (nonatomic, strong) NSArray * arr1;
_mutArray = [NSMutableArray array]; [_mutArray addObject:@"1"]; _arr1 = [NSArray array]; _arr1 = [_mutArray copy]; NSLog(@"strong修饰NSArray--%p***%@--%p***%@",_arr1,_arr1,_mutArray,_mutArray); [_mutArray addObject:@"2"]; NSLog(@"strong修饰NSArray,传进来的mutarArr更改后--%p***%@--%p***%@",_arr1,_arr1,_mutArray,_mutArray);
2.copy修饰NSArray,正确的写法。
_mutArray = [NSMutableArray array]; [_mutArray addObject:@"1"]; // _arr3 = [_mutArray copy]; //copy方法会为_arr1开辟新的内存,所以_arr1不会随着mutArray改变; // 如果直接赋值,就会改变_arr1,因为直接赋值指向的是同一个地址的区域 _arr3 = [NSArray array]; _arr3 = [_mutArray copy]; NSLog(@"copy修饰NSArray后--%p***%@--%p***%@",_arr3,_arr3,_mutArray,_mutArray); [_mutArray addObject:@"2"]; NSLog(@"copy修饰NSArray后--%p***%@--%p***%@",_arr3,_arr3,_mutArray,_mutArray);
根据测试结果,得到
1.用copy修饰,copy方法 NSLog---0x600001e8cc60***(1) --0x6000012d53b0***(1,2) 2.用copy修饰,mutableCopy方法 NSLog---0x600001410f90***(1) --0x600001410ff0***(1,2) 3.用strong修饰,copy方法 NSLog---0x60000363aa80***(1) --x600003a58ab0***(1,2) 4.用strong修饰,mutableCopy方法 NSLog---0x60000375e9a0***(1) --0x60000375e760***(1,2) 结论:不管是copy还是strong,都可以修饰NSArray,_arr1(_arr3)和_mutArray的指针都是指向同一片区域
mutableArray可以通过copy方法变成array,array可以通过mutableCopy方法变成mutableArr
如果直接赋值(_arr3 = _mutArray) ,copy修饰的_arr3还是会随着mutArray的变化而变化
3.strong修饰NSMutableArray,正确的写法,不会出现问题,但不能用copy方法。
_mutArray = [NSMutableArray array]; [_mutArray addObject:@"1"]; _mutArr2 = [NSMutableArray array]; _mutArr2 = [_mutArray mutableCopy]; NSLog(@"strong修饰NSArray--%p***%@--%p***%@",_mutArr2,_mutArr2,_mutArray,_mutArray); [_mutArray addObject:@"2"]; NSLog(@"strong修饰NSArray后--%p***%@--%p***%@",_mutArr2,_mutArr2,_mutArray,_mutArray); [_mutArr2 addObject:@"3"];
4.copy修饰的NSMutableArray
NSArray * arr = @[@"1",@"2"]; // _mutArr4 = [arr mutableCopy];//正确写法,用copy修饰NSMutableArray也不汇报错 _mutArr4 = [arr mutableCopy]; NSLog(@"%p--%@ \n %p***%@",_mutArr4,_mutArr4,arr,arr); [_mutArr4 addObject:@"3"]; //-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x600000a36280 NSLog(@"%p--%@ \n %p***%@",_mutArr4,_mutArr4,arr,arr);
根据测试结果,得到:
1.用copy修饰,copy方法 NSLog---0x600001e8cc60***(1) --0x6000012d53b0***(1,2),setter会crash 2.用copy修饰,mutableCopy方法 NSLog---0x600000679710(1) --0x600000836d40***(1,2),setter不会crash 3.用strong修饰,copy方法 NSLog---0x60000363aa80***(1) --x600003a58ab0***(1,2),setter会crash 4.用strong修饰,mutableCopy方法 NSLog---0x60000375e9a0***(1) --0x60000375e760***(1,2),setter 不会crash
OMT:
1.尽量避免直接赋值的操作_AArray = _BArray,如果B是个可变数组,这样赋值会改变A的内容,产生意想不到的结果;
2.正确的用法是initWithBArray等方法,不过更推荐根据可变不可变的情况用copy或mutableCopy一行代码搞定;
3.mutableArray可以通过copy方法变成array,array可以通过mutableCopy方法变成mutableArr,主要看接收者是可变还是不可变。
4.NSArray用什么方法倒无所谓,mutableArray一定不能用copy方法来初始化,不管ta是strong还是copy修饰,一旦用copy方法初始化,
再调用Setter方法会Crash;