iOS - copy/strong

copy/Strong的区别

修饰属性时的区别

NSString在Objective-C中中是一种非常特殊的对象,其引用系数不受引用计数规则的控制。NSString对象不管是alloc、retain还是release,其引用计数都是-1。(用CFGetRetainCount((__bridge CFTypeRef)(str))打印是1152921504606846975,在MRC下用retainCount打印是-1)

修饰属性时:
strong和retain是浅拷贝,强引用,指向原内存地址,原内存地址引用记数+1
copy是深拷贝,复制原内存里的值,并存到新的地址中。原内存地址引用记数不变。

NSString赋值来源于NSMutableString时:
用strong的时候,NSString的指针指向NSMutableString的地址,值会随NSMutableString的修改而修改。
用copy的时候,NSString是用NSMutableString的值创建新的对象,指向的是新的地址,值不会随NSMutableString的修改而修改。

之前使用下划线赋值(_string = str)导致不管是ARC还是MRC,不管是strong、copy、还是retain,都是指向原地址,会随原值的修改而改变。在ARC下,原retainCount都会+1(系统自动retain),在MRC下,原retainCount不变(不写retain的情况,如果写了,则跟ARC一样retainCount+1)
这块实验出问题的原因:
赋值时用的 _ 下划线调用的,_string = str;
_下划线调用的其实是局部变量,没有关键字修饰,或关键字不生效。
self.string = str;
self.调用的才是属性,会被关键字修饰。

@property (strong, nonatomic) NSString * string;
@property (copy, nonatomic) NSString * cString;
@property (retain, nonatomic) NSString * rString;


 NSMutableString * str = [[NSMutableString alloc] initWithString:@"hello"];
    NSLog(@"str      = %@(%p) str retain  count = %ld\n",str,str,str.retainCount);
    //_string = str;
    self.string = str;
    NSLog(@"_stirng  = %@(%p) str retain  count = %ld\n",_string,_string,str.retainCount);

    self.cString = str;
    NSLog(@"_cString = %@(%p) str retain  count = %ld\n",_cString,_cString,str.retainCount);

    self.rString = str;
    NSLog(@"_rString = %@(%p) str retain  count = %ld\n",_rString,_rString,str.retainCount);
    
    NSLog(@"//修改 str");
    [str appendString:@" word"];
  
    NSLog(@"str      = %@(%p) str retain  count = %ld\n",str,str,str.retainCount);
    NSLog(@"_stirng  = %@(%p) str retain  count = %ld\n",_string,_string,str.retainCount);
    NSLog(@"_cString = %@(%p) str retain  count = %ld\n",_cString,_cString,str.retainCount);
    NSLog(@"_rString = %@(%p) str retain  count = %ld\n",_rString,_rString,str.retainCount);

//输出结果

2019-02-20 16:40:54.761 Test[30574:8646276] str      = hello(0x7fa17252ba00) str retain  count = 1
2019-02-20 16:40:54.761 Test[30574:8646276] _stirng  = hello(0x7fa17252ba00) str retain  count = 2
2019-02-20 16:40:54.761 Test[30574:8646276] _cString = hello(0x7fa172523b30) str retain  count = 2
2019-02-20 16:40:54.761 Test[30574:8646276] _rString = hello(0x7fa17252ba00) str retain  count = 3

2019-02-20 16:40:54.762 Test[30574:8646276] //修改 str
2019-02-20 16:40:54.762 Test[30574:8646276] str      = hello word(0x7fa17252ba00) str retain  count = 3
2019-02-20 16:40:54.762 Test[30574:8646276] _stirng  = hello word(0x7fa17252ba00) str retain  count = 3
2019-02-20 16:40:54.762 Test[30574:8646276] _cString = hello(0x7fa172523b30) str retain  count = 3
2019-02-20 16:40:54.762 Test[30574:8646276] _rString = hello word(0x7fa17252ba00) str retain  count = 3

在赋值时copy和mutableCopy的区别

1、可变 = 不可变
copy:浅拷贝,指向原内存地址。
mutableCopy:深拷贝,复制str内容放到新内存地址中。
(与修饰属性的时候有区别,需要注意!!!)

不可变类型copy给可变类型后,如mStr = [str copy];
mStr再调用[mStr appendString:@" world"],程序会闪退。

2、不可变 = 不可变,copy浅拷贝,引用记数+1(NSString除外,引用记数为-1),mutableCopy深拷贝。

3、不可变 = 可变,copy和mutableCopy一样都是深拷贝,复制内容放到新内存地址中。

4、可变 = 可变,copy和mutableCopy一样都是深拷贝,复制内容放到新内存地址中。

5、局部变量 object = object,深拷贝弱引用

    NSString * str = @"hello";
    
    NSMutableString * mStr = [str copy];
    NSMutableString * mStr1 = [str mutableCopy];
(lldb) p str
(__NSCFConstantString *) $0 = 0x0000000102ed0090 @"hello"
(lldb) p mStr
(__NSCFConstantString *) $1 = 0x0000000102ed0090 @"hello"
(lldb) p mStr1
(__NSCFString *) $2 = 0x0000000283ad42a0 @"hello"

为什么xib链接的property要用weak。

因为通过xib添加到view上的UI控件,会存放在view.subViews的数组中,被view强引用,不需要使用strong对UI控件进行再次强引用。
如果使用strong的话,在控件调用removeFromSuperview的时候会因为还被controller强引用而无法释放,只能等controller被释放才会被释放。

你可能感兴趣的:(iOS - copy/strong)