今天说一下ios的修饰关键字copy与strong在使用时的区别
对可变对象NSMutableString
@property (strong, nonatomic) NSMutableString *retainMstr;
@property (copy, nonatomic) NSMutableString *mStr;
NSMutableString *mutableStr = [NSMutableString stringWithString:@"hello"];
self.retainMstr = mutableStr;
self.mStr = mutableStr;
NSLog(@"原 : %@ %p:",mutableStr,mutableStr);
NSLog(@"strong: %@ %p:",self.retainMstr,self.retainMstr);
NSLog(@"copy : %@ %p:",self.mStr,self.mStr);
打印输出
2020-02-16 19:56:01.890207+0800 iosDemo1[19551:1823733] 原 : hello 0x600003776c10:
2020-02-16 19:56:01.890372+0800 iosDemo1[19551:1823733] strong: hello 0x600003776c10:
2020-02-16 19:56:01.890522+0800 iosDemo1[19551:1823733] copy : hello 0xf146d5c1dcf28cc0:
结论
可以看出,对可变对象:
strong修饰,赋值时只是拷贝了指针,没有开辟新内存.
而copy修饰,赋值时开辟了新内存.
我们可以大胆猜测,如果修改了原数据,那么就会影响strong修饰的对象,而不会影响copy修饰的对象
开始修改操作
[mutableStr appendString:@" world"];
NSLog(@"原 : %@ %p:",mutableStr,mutableStr);
NSLog(@"strong: %@ %p:",self.retainMstr,self.retainMstr);
NSLog(@"copy : %@ %p:",self.mStr,self.mStr);
打印输出
2020-02-16 19:56:01.890628+0800 iosDemo1[19551:1823733] 原 : hello world 0x600003776c10:
2020-02-16 19:56:01.890700+0800 iosDemo1[19551:1823733] strong: hello world 0x600003776c10:
2020-02-16 19:56:01.890788+0800 iosDemo1[19551:1823733] copy : hello 0xf146d5c1dcf28cc0:
测试结果表明我们的猜测是正确的.
重点!!!
如果赋值的数据是可变对象,如果不希望受到它的修改而影响,那就用copy修饰.
对不可变对象NSString
@property (strong, nonatomic) NSString *str_strong;
@property (copy, nonatomic) NSString *str_copy;
NSString *str1 = @"123";
self.str_strong = str1;
self.str_copy = str1;
NSLog(@"原 : %@ %p:",str1,str1);
NSLog(@"strong: %@ %p:",self.str_strong,self.str_strong);
NSLog(@"copy : %@ %p:",self.str_copy,self.str_copy);
str1 = @"456";
NSLog(@"原 : %@ %p:",str1,str1);
NSLog(@"strong: %@ %p:",self.str_strong,self.str_strong);
NSLog(@"copy : %@ %p:",self.str_copy,self.str_copy);
打印输出
2020-02-16 20:07:06.074246+0800 iosDemo1[19703:1863001] 原 : 123 0x108a0c040:
2020-02-16 20:07:06.074367+0800 iosDemo1[19703:1863001] strong: 123 0x108a0c040:
2020-02-16 20:07:06.074447+0800 iosDemo1[19703:1863001] copy : 123 0x108a0c040:
2020-02-16 20:07:06.074536+0800 iosDemo1[19703:1863001] 原 : 456 0x108a0c0c0:
2020-02-16 20:07:06.074610+0800 iosDemo1[19703:1863001] strong: 123 0x108a0c040:
2020-02-16 20:07:06.074684+0800 iosDemo1[19703:1863001] copy : 123 0x108a0c040:
结论
可以看出,对于不可变字符串:
strong修饰和copy修饰,都是浅拷贝,指针复制,并没有开辟新的内存空间.
这个时候,可能有人要说了:既然是浅拷贝,那修改源数据应该会影响它们啊.然而事实并没有产生影响.
因为对不可变字符串重新赋值时,系统又为其分配了新的内存空间.str1的指针变了,指向了新的内存空间. 但是copy和strong的指针没有改变.指向的依然是原来str1指向的那块内存.
对可变对象NSMutableArray
@property (strong, nonatomic) NSMutableArray *strong_Array;
@property (copy, nonatomic) NSMutableArray *copyy_Array;
NSMutableArray *mArr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
self.strong_Array = mArr;
self.copyy_Array = mArr;
NSLog(@"原 : %@ %p:",mArr,mArr);
NSLog(@"strong: %@ %p:",self.strong_Array,self.strong_Array);
NSLog(@"copy : %@ %p:",self.copyy_Array,self.copyy_Array);
[self.strong_Array addObject:@"3"];
NSLog(@"修改strong对象后----------------");
NSLog(@"原 : %@ %p:",mArr,mArr);
NSLog(@"strong: %@ %p:",self.strong_Array,self.strong_Array);
NSLog(@"copy : %@ %p:",self.copyy_Array,self.copyy_Array);
[self.copyy_Array addObject:@"4"];
打印输出
2020-02-16 20:27:35.401768+0800 iosDemo1[19956:1932798] 原 : (
1,
2
) 0x6000036e2a60:
2020-02-16 20:27:35.401909+0800 iosDemo1[19956:1932798] strong: (
1,
2
) 0x6000036e2a60:
2020-02-16 20:27:35.402002+0800 iosDemo1[19956:1932798] copy : (
1,
2
) 0x6000038f6160:
2020-02-16 20:27:35.402076+0800 iosDemo1[19956:1932798] 修改strong对象后----------------
2020-02-16 20:27:35.402172+0800 iosDemo1[19956:1932798] 原 : (
1,
2,
3
) 0x6000036e2a60:
2020-02-16 20:27:35.402256+0800 iosDemo1[19956:1932798] strong: (
1,
2,
3
) 0x6000036e2a60:
2020-02-16 20:27:35.402338+0800 iosDemo1[19956:1932798] copy : (
1,
2
) 0x6000038f6160:
2020-02-16 20:27:35.402449+0800 iosDemo1[19956:1932798] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x6000038f6160
(lldb)
可以看出:
修改strong对象后,会影响源数据,当然修改源数据也会影响strong修饰的对象.而不会影响copy修饰的对象.因为copy开辟新内存了.
而对copy进行修改的时候直接crash. 因为copy返回的是不可变对象.
结论
对于可变容器类对象(NSMutableArray,NSMutableDictionary,NSMutableSet...)
要用strong修饰
大总结:
对于不可变对象:strong和copy修饰,都是浅拷贝, 当对源数据修改时并无影响,用哪个都可以.
对于可变对象:strong浅拷贝,copy深拷贝.
如果不希望数据收到源数据的修改而影响就用copy.反之用strong
对可变对象修饰:一定要用strong. 因为copy返回的是不可变对象.
如有错误,欢迎指正!