iOS strong vs copy
一、NSString
@property (nonatomic, strong) NSString *myStrongStr;
@property (nonatomic, copy) NSString *myCopyStr;
- 原对象不可变时,两种情况下都只是指针拷贝,计数+1。
NSString *originStr = @"11";
self.myCopyStr = originStr;
self.myStrongStr = originStr;
NSLog(@"originStr: %p", originStr);
NSLog(@"myCopyStr: %p", self.myCopyStr);
NSLog(@"myStrongStr: %p", self.myStrongStr);
2017-09-21 17:56:58.489 iOSLockDemo[40745:2801462] originStr: 0x10ba4a078
2017-09-21 17:56:58.490 iOSLockDemo[40745:2801462] myCopyStr: 0x10ba4a078
2017-09-21 17:56:58.490 iOSLockDemo[40745:2801462] myStrongStr: 0x10ba4a078
- 原对象可变时,
strong
修饰的对象,是指针拷贝,引用计数+1;copy
修饰的对象是内存拷贝,生成新对象。
NSMutableString *originStr = [@"11" mutableCopy];
self.myCopyStr = originStr;
self.myStrongStr = originStr;
NSLog(@"originStr: %p", originStr);
NSLog(@"myCopyStr: %p", self.myCopyStr);
NSLog(@"myStrongStr: %p", self.myStrongStr);
2017-09-21 18:04:44.904 iOSLockDemo[40919:2812754] originStr: 0x60000006d780
2017-09-21 18:04:44.904 iOSLockDemo[40919:2812754] myCopyStr: 0xa000000000031312
2017-09-21 18:04:44.905 iOSLockDemo[40919:2812754] myStrongStr: 0x60000006d780
二、集合
- 原集合
不可变
,strong
和copy
没有区别,集合本身和集合内的对象都是指针拷贝,引用计数+1。
NSArray *arr = @[@"aa"];
self.myStrongArr = arr;
self.myCopyArr = arr;
NSLog(@"arr: %p", arr);
NSLog(@"arr object: %p", arr[0]);
NSLog(@"myStrongArr: %p", self.myStrongArr);
NSLog(@"myStrongArr object: %p", self.myStrongArr[0]);
NSLog(@"myCopyArr: %p", self.myCopyArr);
NSLog(@"myCopyArr object: %p", self.myCopyArr[0]);
2017-09-21 18:17:48.400 iOSLockDemo[41198:2832193] arr: 0x60000001fe40
2017-09-21 18:17:48.400 iOSLockDemo[41198:2832193] arr object: 0x10bb1a080
2017-09-21 18:17:48.401 iOSLockDemo[41198:2832193] myStrongArr: 0x60000001fe40
2017-09-21 18:17:48.401 iOSLockDemo[41198:2832193] myStrongArr object: 0x10bb1a080
2017-09-21 18:17:48.401 iOSLockDemo[41198:2832193] myCopyArr: 0x60000001fe40
2017-09-21 18:17:48.401 iOSLockDemo[41198:2832193] myCopyArr object: 0x10bb1a080
- 原集合
可变
,strong
是集合本身和集合内对象都是指针拷贝,引用计数+1;copy
则是集合本身是内存拷贝,生成新对象;而集合内对象都是指针拷贝,引用计数+1。
NSArray *arr = [@[@"aa"] mutableCopy];
self.myStrongArr = arr;
self.myCopyArr = arr;
NSLog(@"arr: %p", arr);
NSLog(@"arr object: %p", arr[0]);
NSLog(@"myStrongArr: %p", self.myStrongArr);
NSLog(@"myStrongArr object: %p", self.myStrongArr[0]);
NSLog(@"myCopyArr: %p", self.myCopyArr);
NSLog(@"myCopyArr object: %p", self.myCopyArr[0]);
2017-09-21 18:20:59.494 iOSLockDemo[41288:2838292] arr: 0x60000005c740
2017-09-21 18:20:59.494 iOSLockDemo[41288:2838292] arr object: 0x10f3c7080
2017-09-21 18:20:59.494 iOSLockDemo[41288:2838292] myStrongArr: 0x60000005c740
2017-09-21 18:20:59.494 iOSLockDemo[41288:2838292] myStrongArr object: 0x10f3c7080
2017-09-21 18:20:59.495 iOSLockDemo[41288:2838292] myCopyArr: 0x6000000134f0
2017-09-21 18:20:59.495 iOSLockDemo[41288:2838292] myCopyArr object: 0x10f3c7080
以上集合的规则也适用NSDictionary和NSSet。
总结
Note:property = ivar + getter + setter;
-
strong
修饰的property
,生成以下setter
方法:
- (void)setMyStrongStr:(NSString *)myStrongStr {
_myStrongStr = myStrongStr;
}
- (void)setMyStrongArr:(NSArray *)myStrongArr {
_myStrongArr = myStrongArr;
}
-
copy
修饰的property
,生成以下setter
方法:
- (void)setMyStrongStr:(NSString *)myStrongStr {
_myStrongStr = [myStrongStr copy];
}
- (void)setMyStrongArr:(NSArray *)myStrongArr {
_myStrongArr = [myStrongArr copy];
}
那么到底什么情况下使用copy
呢?看个例子:
NSMutableString *originStr = [@"11" mutableCopy];
self.myCopyStr = originStr;
NSLog(@"originStr address: %p", originStr);
NSLog(@"myCopyStr address: %p", self.myCopyStr);
NSString *testStr = self.myCopyStr;
NSLog(@"testStr address: %p", testStr);
NSLog(@"myCopyStr value: %@", self.myCopyStr);
NSLog(@"change testStr equal 'hahha'...");
testStr = @"hahha";
NSLog(@"myCopyStr value: %@", self.myCopyStr);
NSLog(@"testStr address: %p", testStr);
2017-09-21 18:38:44.743 iOSLockDemo[41684:2865187] originStr address: 0x60800006dd80
2017-09-21 18:38:44.743 iOSLockDemo[41684:2865187] myCopyStr address: 0xa000000000031312
2017-09-21 18:38:44.743 iOSLockDemo[41684:2865187] testStr address: 0xa000000000031312
2017-09-21 18:38:44.743 iOSLockDemo[41684:2865187] myCopyStr value: 11
2017-09-21 18:38:44.745 iOSLockDemo[41684:2865187] change testStr equal 'hahha'...
2017-09-21 18:38:44.745 iOSLockDemo[41684:2865187] myCopyStr value: 11
2017-09-21 18:38:44.746 iOSLockDemo[41684:2865187] testStr address: 0x10a877130
当我们引用copy
修饰的myCopyStr
时,testStr
此时只是指针拷贝,并没有生成新的对象,当我们改变testStr
以后,你会发现testStr
内存地址变了,也就是说,当runtime
发现我们我们试图通过指针改变一个copy
修饰的属性,会自动拷贝生成一个新的对象,并将当前指针执行新的内存地址。
因此对于字符串NSString
来说,如果你不希望当前属性变量被原对象干扰时,就用copy
;否则用strong
。
NSArray *arr = [@[@"aa"] mutableCopy];
self.myStrongArr = arr;
NSLog(@"myStrongArr: %@", self.myStrongArr);
[((NSMutableArray *)self.myStrongArr) addObject:@"bb"];
NSLog(@"myStrongArr: %@", self.myStrongArr);
2017-09-21 18:50:10.611 iOSLockDemo[41913:2877784] myStrongArr: (
aa
)
2017-09-21 18:50:10.611 iOSLockDemo[41913:2877784] myStrongArr: (
aa,
bb
)
对于集合来说,如果你不希望发生通过((NSMutableArray *)self.myStrongArr)
改变集合的对象数量的事情发生,就用copy
,否则用strong
。