OC 属性 strong 和 copy 的那些事

一直对 strongcopy 不甚了解,今天决定做个小实验。

1. 先创建四个属性

@property (nonatomic, strong) NSArray *arrStrong;
@property (nonatomic, copy) NSArray *arrCopy;
@property (nonatomic, strong) NSMutableArray *mArrStrong;
@property (nonatomic, copy) NSMutableArray *mArrCopy;

2. 然后 NSLog

    NSLog(@" ==== start ====");
    
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempArr", tempArr, CFGetRetainCount((__bridge CFTypeRef)tempArr), [tempArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    
    NSLog(@"\n------------------------------");
    NSLog(@" ==== self.arrStrong start ====");

    self.arrStrong = tempArr;
    NSLog(@"\n");
    NSLog(@" ==== self.arrStrong = tempArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempArr", tempArr, CFGetRetainCount((__bridge CFTypeRef)tempArr), [tempArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrStrong", _arrStrong, CFGetRetainCount((__bridge CFTypeRef)_arrStrong), [_arrStrong componentsJoinedByString:@","]);

    self.arrStrong = tempMutableArr;
    NSLog(@"\n");
    NSLog(@" ==== self.arrStrong = tempMutableArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrStrong", _arrStrong, CFGetRetainCount((__bridge CFTypeRef)_arrStrong), [_arrStrong componentsJoinedByString:@","]);

    NSLog(@"\n------------------------------");
    NSLog(@" ==== self.arrCopy start ====");

    self.arrCopy = tempArr;
    NSLog(@"\n");
    NSLog(@" ==== self.arrCopy = tempArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempArr", tempArr, CFGetRetainCount((__bridge CFTypeRef)tempArr), [tempArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrCopy", _arrCopy, CFGetRetainCount((__bridge CFTypeRef)_arrCopy), [_arrCopy componentsJoinedByString:@","]);
    
    self.arrCopy = tempMutableArr;
    NSLog(@"\n");
    NSLog(@" ==== self.arrCopy = tempMutableArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrCopy", _arrCopy, CFGetRetainCount((__bridge CFTypeRef)_arrCopy), [_arrCopy componentsJoinedByString:@","]);

    NSLog(@"\n------------------------------");
    NSLog(@" ==== change tempMutableArr start ====");

    [tempMutableArr addObject:@"增加一个值"];
    NSLog(@"\n");
    NSLog(@" ==== [tempMutableArr addObject:@\"增加一个值\"]  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrStrong", _arrStrong, CFGetRetainCount((__bridge CFTypeRef)_arrStrong), [_arrStrong componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _arrCopy", _arrCopy, CFGetRetainCount((__bridge CFTypeRef)_arrCopy), [_arrCopy componentsJoinedByString:@","]);

    NSLog(@"\n------------------------------");
    NSLog(@" ==== self.mArrStrong start ====");

    self.mArrStrong = tempArr;
    NSLog(@"\n");
    NSLog(@" ==== self.mArrStrong = tempArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempArr", tempArr, CFGetRetainCount((__bridge CFTypeRef)tempArr), [tempArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrStrong", _mArrStrong, CFGetRetainCount((__bridge CFTypeRef)_mArrStrong), [_mArrStrong componentsJoinedByString:@","]);
//    [self.mArrStrong addObject:@"增加一个值"]; // crash
//    NSLog(@" ==== [self.mArrStrong addObject:@\"增加一个值\"]  ====");
//    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrStrong", _mArrStrong, CFGetRetainCount((__bridge CFTypeRef)_mArrStrong), [_mArrStrong componentsJoinedByString:@","]);

    self.mArrStrong = tempMutableArr;
    NSLog(@"\n");
    NSLog(@" ==== self.mArrStrong = tempMutableArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrStrong", _mArrStrong, CFGetRetainCount((__bridge CFTypeRef)_mArrStrong), [_mArrStrong componentsJoinedByString:@","]);
    [self.mArrStrong addObject:@"增加一个值"];
    NSLog(@" ==== [self.mArrStrong addObject:@\"增加一个值\"]  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrStrong", _mArrStrong, CFGetRetainCount((__bridge CFTypeRef)_mArrStrong), [_mArrStrong componentsJoinedByString:@","]);

    NSLog(@"\n------------------------------");
    NSLog(@" ==== self.mArrCopy start ====");
    self.mArrCopy = tempArr;
    NSLog(@"\n");
    NSLog(@" ==== self.mArrCopy = tempArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempArr", tempArr, CFGetRetainCount((__bridge CFTypeRef)tempArr), [tempArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrCopy", _mArrCopy, CFGetRetainCount((__bridge CFTypeRef)_mArrCopy), [_mArrCopy componentsJoinedByString:@","]);
//    [self.mArrCopy addObject:@"增加一个值"]; // crash
//    NSLog(@" ==== [self.mArrCopy addObject:@\"增加一个值\"]  ====");
//    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrCopy", _mArrCopy, CFGetRetainCount((__bridge CFTypeRef)_mArrCopy), [_mArrCopy componentsJoinedByString:@","]);
    
    self.mArrCopy = tempMutableArr;
    NSLog(@"\n");
    NSLog(@" ==== self.mArrCopy = tempMutableArr  ====");
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === tempMutableArr", tempMutableArr, CFGetRetainCount((__bridge CFTypeRef)tempMutableArr), [tempMutableArr componentsJoinedByString:@","]);
    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrCopy", _mArrCopy, CFGetRetainCount((__bridge CFTypeRef)_mArrCopy), [_mArrCopy componentsJoinedByString:@","]);
//    [self.mArrCopy addObject:@"增加一个值"]; // crash
//    NSLog(@" ==== [self.mArrCopy addObject:@\"增加一个值\"]  ====");
//    NSLog(@"内存地址 = %p, retainCount = %li, 值 = %@, === _mArrCopy", _mArrCopy, CFGetRetainCount((__bridge CFTypeRef)_mArrCopy), [_mArrCopy componentsJoinedByString:@","]); 

3. 打印输出

 ==== start ====
内存地址 = 0x6000038bb680, retainCount = 1, 值 = temp arr, === tempArr
内存地址 = 0x6000034d9260, retainCount = 1, 值 = temp mutable arr, === tempMutableArr

------------------------------
 ==== self.arrStrong start ====


 ==== self.arrStrong = tempArr  ====
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === tempArr
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === _arrStrong


 ==== self.arrStrong = tempMutableArr  ====
内存地址 = 0x6000034d9260, retainCount = 2, 值 = temp mutable arr, === tempMutableArr
内存地址 = 0x6000034d9260, retainCount = 2, 值 = temp mutable arr, === _arrStrong

------------------------------
 ==== self.arrCopy start ====


 ==== self.arrCopy = tempArr  ====
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === tempArr
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === _arrCopy


 ==== self.arrCopy = tempMutableArr  ====
内存地址 = 0x6000034d9260, retainCount = 2, 值 = temp mutable arr, === tempMutableArr
内存地址 = 0x6000038bb770, retainCount = 1, 值 = temp mutable arr, === _arrCopy

------------------------------
 ==== change tempMutableArr start ====


 ==== [tempMutableArr addObject:@"增加一个值"]  ====
内存地址 = 0x6000034d9260, retainCount = 2, 值 = temp mutable arr,增加一个值, === tempMutableArr
内存地址 = 0x6000034d9260, retainCount = 2, 值 = temp mutable arr,增加一个值, === _arrStrong
内存地址 = 0x6000038bb770, retainCount = 1, 值 = temp mutable arr, === _arrCopy

------------------------------
 ==== self.mArrStrong start ====


 ==== self.mArrStrong = tempArr  ====
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === tempArr
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === _mArrStrong


 ==== self.mArrStrong = tempMutableArr  ====
内存地址 = 0x6000034d9260, retainCount = 3, 值 = temp mutable arr,增加一个值, === tempMutableArr
内存地址 = 0x6000034d9260, retainCount = 3, 值 = temp mutable arr,增加一个值, === _mArrStrong
 ==== [self.mArrStrong addObject:@"增加一个值"]  ====
内存地址 = 0x6000034d9260, retainCount = 3, 值 = temp mutable arr,增加一个值,增加一个值, === _mArrStrong

------------------------------
 ==== self.mArrCopy start ====


 ==== self.mArrCopy = tempArr  ====
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === tempArr
内存地址 = 0x6000038bb680, retainCount = 2, 值 = temp arr, === _mArrCopy


 ==== self.mArrCopy = tempMutableArr  ====
内存地址 = 0x6000034d9260, retainCount = 3, 值 = temp mutable arr,增加一个值,增加一个值, === tempMutableArr
内存地址 = 0x6000034cff30, retainCount = 1, 值 = temp mutable arr,增加一个值,增加一个值, === _mArrCopy

4. 分析结果

NSArray retainCount = 1NSMutableArray retainCount = 1
NSArray strong地址不变 retainCount = 2地址不变,retainCount = 2,操作原地址数据会改变当前值
NSArray copy地址不变 retainCount = 2地址变化,retainCount = 1
NSMutableArray strong地址不变 retainCount = 2,此时操作属性会 crash地址不变,retainCount = 2
NSMutableArray copy地址不变 retainCount = 2,此时操作属性会 crash地址变化,retainCount = 1,操作属性 crash

5. 得出结论

  • NSArray 最好使用 copy 修饰
  • NSMutableArray 最好用 strong 修饰
  • NSMutableArrayNSArray 值需要使用 [NSMutableArray arrayWithArray:tempArr] 方式
    原文作者:CharlesQiu
    原文地址: https://segmentfault.com/a/1190000016752711
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞