iOS知识搜集

iOS strong vs copy

2017-09-21  本文已影响21人  wtqhy14615

iOS strong vs copy

一、NSString

@property (nonatomic, strong) NSString *myStrongStr;
@property (nonatomic, copy) NSString *myCopyStr;
  1. 原对象不可变时,两种情况下都只是指针拷贝,计数+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
  1. 原对象可变时,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

二、集合

  1. 原集合不可变strongcopy没有区别,集合本身和集合内的对象都是指针拷贝,引用计数+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

  1. 原集合可变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;

  1. strong修饰的property,生成以下setter方法:
- (void)setMyStrongStr:(NSString *)myStrongStr {
    _myStrongStr = myStrongStr;
}

- (void)setMyStrongArr:(NSArray *)myStrongArr {
    _myStrongArr = myStrongArr;
}

  1. 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

上一篇 下一篇

猜你喜欢

热点阅读