美文网首页
详细讲解iOS里面深浅拷贝

详细讲解iOS里面深浅拷贝

作者: 丶天空蓝丶 | 来源:发表于2020-01-20 14:16 被阅读0次

    前沿

    属性修饰符包括strong和copy,当问到两者当区别时,一般人都会回答strong是浅拷贝,copy是深拷贝,但是真的是这样吗?

    strong和copy修饰不同属性对比

    1.strong和copy修饰的字符串

    @property (nonatomic, strong) NSString *string2;
    @property (nonatomic, copy) NSString *string3;
    self.string1 = @"123";
    self.string2 = self.string1;
    self.string3 = self.string2;
    self.string1 = @"456";
    NSLog(@"string1: %@ %p",_string1,_string1);
    NSLog(@"string2: %@ %p",_string2,_string2);
    NSLog(@"string3: %@ %p",_string3,_string3);
    

    2020-01-20 14:15:34.735621+0800 TestOC[3913:560591] string1: 456 0x106e112d8
    2020-01-20 14:15:34.735742+0800 TestOC[3913:560591] string2: 123 0x106e10cb8
    2020-01-20 14:15:34.735807+0800 TestOC[3913:560591] string3: 123 0x106e10cb8

    我们可以发现string2和string3都是浅拷贝,可是为什么string2和string3的值没有变成456呢?这是因为string1赋值456的时候相当于重新初始化了,string1自己的指针地址发生改变,重新指向另一块内存。

    那么是不是NSString用strong或copy修饰就没有区别了?其实不然,如果涉及到了NSMutableString,就会看到区别。

    @property (nonatomic, copy) NSString *string3;
    @property (nonatomic, strong) NSMutableString *string4;
    
    self.string4 = [[NSMutableString alloc] init];
    [self.string4 setString:@"111"];
    self.string2 = self.string4;
    self.string3 = self.string4;
    [self.string4 appendString:@"222"];
    
    NSLog(@"string2: %@ %p",_string2,_string2);
    NSLog(@"string3: %@ %p",_string3,_string3);
    NSLog(@"string4: %@ %p",_string4,_string4);
    

    2020-01-20 14:30:58.853710+0800 TestOC[4092:595407] string2: 111222 0x600002d14c30
    2020-01-20 14:30:58.853816+0800 TestOC[4092:595407] string3: 111 0xb200c98b0cb802b3
    2020-01-20 14:30:58.853879+0800 TestOC[4092:595407] string4: 111222 0x600002d14c30

    此时我们可以发现,当拷贝的对象是一个NSMutableString,用strong修饰的NSString是浅拷贝,用copy修饰的则是深拷贝。此时,为什么NSString使用copy修饰也就可以理解了。使用copy修饰之后,即使属性拷贝来自可变字符串,也会被深拷贝成不可变字符串,也就是源字符串修改之后不会影响到属性字符串,增强了代码的健壮性。

    注意:使用copy出来的字符串不管源对象是可变字符串还是不可变字符串,都会变成不可变字符串。因此不可变字符串(NSMutableString)创建成属性的时候不能用copy修饰,需要用strong修饰。

    总结:copy出来的字符串一定是不可变字符串,如果传入的是可变字符串,会发生深拷贝为不可变字符串,否则为浅拷贝。strong修饰的都是浅拷贝。

    2.copy和mutableCopy出来的字符串

        NSString *string2;
        NSString *string3;
        string2 = [string1 copy];
        string3 = [string1 mutableCopy];
        string1 = @"456"
        NSLog(@"string1: %@ %p",string1,string1);
        NSLog(@"string2: %@ %p",string2,string2);
        NSLog(@"string3: %@ %p",string3,string3);
    

    2020-01-20 15:03:54.962621+0800 TestOC[4372:675991] string1: 456 0x10e6512b8
    2020-01-20 15:03:54.962761+0800 TestOC[4372:675991] string2: 123 0x10e650cb8
    2020-01-20 15:03:54.962830+0800 TestOC[4372:675991] string3: 123 0x600001233600

    可以看出,NSString的mutableCopy也是深拷贝,并且拷贝出来的是一个可变字符串,因为用NSString创建的,尽管本质是一个可变字符串,但是不可以当初可变字符串进行操作,如appendString会报错。

        NSMutableString *string2;
        NSMutableString *string3;
        string2 = [string1 copy];
        string3 = [string1 mutableCopy];
        [string1 appendString:@"456"];
        NSLog(@"string1: %@ %p",string1,string1);
        NSLog(@"string2: %@ %p",string2,string2);
        NSLog(@"string3: %@ %p",string3,string3);
    

    2020-01-20 15:12:01.395989+0800 TestOC[4439:696226] string1: 123456 0x600001775e00
    2020-01-20 15:12:01.396136+0800 TestOC[4439:696226] string2: 123 0x94c4c7fe69a3db5b
    2020-01-20 15:12:01.396191+0800 TestOC[4439:696226] string3: 123 0x600001774ba0

    结论:mutablecopy,一定是深拷贝,拷贝出来的一定是可变字符串,即使传入的是不可变字符串。
    注意:NSString和NSMutableString使用不同拷贝,本质可能发生改变。如NSMutableString创建string用copy赋值,此时用NSString的方法赋值会报警告,而用NSMutableString的方法则会直接报错。因此如何使用copy和mutablecopy拷贝需要谨慎使用。

    3.strong和copy修饰的数组
    当数组为不可变数组,用strong修饰是浅拷贝,如果源数组是不可变数组,则用copy修饰也是浅拷贝,如果源数组是可变数组,则用copy修饰变成深拷贝。
    当数组为可变数组,用strong修饰是浅拷贝,用copy修饰都是深拷贝,但是会使数组变成不可变数组,从而不能使用可变数组方法。

    总结:针对字符串和数组。
    不可变字符串和不可变数组使用copy修饰,这样可以确保当其拷贝源是可变的时候会进行深拷贝,以免修改源造成数据跟随源数据改变。
    可变数组和可变字符串使用strong修饰,如果使用copy修饰会将其变成不可变,导致使用可变方法是出错。
    当接受值为不可变字符串和不可变数组时,如果接受值为属性,或者源数据为不可变,则可直接用=赋值,否则用copy赋值。
    当接受值为可变字符串和可变数组时,推荐使用mutableCopy赋值,因为这样是深拷贝,源值改变不会影响新值。
    字典和集合同上

    相关文章

      网友评论

          本文标题:详细讲解iOS里面深浅拷贝

          本文链接:https://www.haomeiwen.com/subject/dccdoctx.html