关于copy、mutableCopy的讨论(1)

作者: hanl001 | 来源:发表于2016-12-22 15:56 被阅读102次
    问: 为什么要用 copy 修饰 NSString

    带着问题我们进行如下讨论: 测试代码

    1、不可变字符串copy

        NSString *str = @"string";
        NSLog(@"%p",str);
        
        NSString *strCopy1 = [str copy];
        NSLog(@"%p",strCopy1);
        
        NSMutableString *strCopy2 = [str copy];
        NSLog(@"%p",strCopy2);
        
        NSString *strCopy3 = [str copy];
        NSLog(@"%p",strCopy3);
        
        NSMutableString *strCopy4 = [str copy];
        NSLog(@"%p",strCopy4);
        //如果取消下面的注释,则crash,strCopy2实质还是不可变字符串
    //    [strCopy2 appendString:@"1"];
    

    控制台输出如下

    2016-12-22 14:25:11.636 CopyAndStrong[16067:400558] 0x10adab098
    2016-12-22 14:25:11.636 CopyAndStrong[16067:400558] 0x10adab098
    2016-12-22 14:25:11.637 CopyAndStrong[16067:400558] 0x10adab098
    2016-12-22 14:25:11.637 CopyAndStrong[16067:400558] 0x10adab098
    2016-12-22 14:25:11.637 CopyAndStrong[16067:400558] 0x10adab098
    

    NSString的copy只是相当于“强引用” ,也就是浅拷贝。
    下图是该字符串的isa指针类型,根据名称就可以知道0x10adab098在常量区,存放字符串量,而不论你对一个字符串常量怎么copy,他依然还是静静地在常量区做一个字符串常量

    Snip20161222_5.png

    2、不可变字符串mutableCopy

        NSString *str = @"string";
        NSLog(@"%p",str);
        
        NSString *strMutableCopy1 = [str mutableCopy];
        NSLog(@"%p",strMutableCopy1);
        
        NSMutableString *strMutableCopy2 = [str mutableCopy];
        NSLog(@"%p",strMutableCopy2);
        
        NSString *strMutableCopy3 = [str mutableCopy];
        NSLog(@"%p",strMutableCopy3);
        
        NSMutableString *strMutableCopy4 = [str mutableCopy];
        NSLog(@"%p",strMutableCopy4);
    

    控制台输出如下

    2016-12-22 14:36:20.605 CopyAndStrong[16067:400558] 0x10adab098
    2016-12-22 14:36:20.605 CopyAndStrong[16067:400558] 0x60800007db80
    2016-12-22 14:36:20.605 CopyAndStrong[16067:400558] 0x600000261e40
    2016-12-22 14:36:20.606 CopyAndStrong[16067:400558] 0x608000260300
    2016-12-22 14:36:20.606 CopyAndStrong[16067:400558] 0x60800007db40
    

    每一个mutableCopy的字符串,地址都不同,而且他们的样式和 0x10adab098 明显不同,这里我执行如下代码

    UIView *view = [UIView new];
    NSLog(@"%p",view);  // 输出 `0x7fc4ec503e50`
    

    发现堆区对象的地址和mutableCopy的字符串得到的字符串地址极为相似,得出结论mutableCopy之后的字符串在堆区,而他们的类型其实都是NSMutableString,参考如下截图

    Snip20161222_6.png

    3、可变字符串的copy

        NSString *str = @"string";
        NSLog(@"%p",str);
        NSMutableString *mutableStr = [str mutableCopy];
        NSLog(@"%p",mutableStr);
        
        NSString *MutableStrCopy1 = [mutableStr copy];
        NSLog(@"%p",MutableStrCopy1);
        
        NSMutableString *MutableStrCopy2 = [mutableStr copy];
        NSLog(@"%p",MutableStrCopy2);
        
        NSString *MutableStrCopy3 = [mutableStr copy];
        NSLog(@"%p",MutableStrCopy3);
        
        NSMutableString *MutableStrCopy4 = [mutableStr copy];
        NSLog(@"%p",MutableStrCopy4);
        
    //    [MutableStrCopy2 appendString:@"1"];//取消注释就会crash,copy之后实际是不可变字符串
    

    控制台输出如下

    2016-12-22 14:54:26.257 CopyAndStrong[16151:410074] 0x106181098
    2016-12-22 14:54:26.257 CopyAndStrong[16151:410074] 0x608000078240
    2016-12-22 14:54:26.258 CopyAndStrong[16151:410074] 0xa00676e697274736
    2016-12-22 14:54:26.258 CopyAndStrong[16151:410074] 0xa00676e697274736
    2016-12-22 14:54:26.258 CopyAndStrong[16151:410074] 0xa00676e697274736
    2016-12-22 14:54:26.258 CopyAndStrong[16151:410074] 0xa00676e697274736
    

    四次copy,结果都是同一个地址,而且这里打印出来的地址有点奇怪,我在控制台看到如下描述:

    Snip20161222_8.png
    查了资料发现一个叫做Tagged Pointer的东西,这里不做解释。。。

    4、可变字符串的mutableCopy

        NSString *str = @"string";
        NSLog(@"%p",str);
        NSMutableString *mutableStr = [str mutableCopy];
        NSLog(@"%p",mutableStr);
        
        NSString *MutableStrMutableCopy1 = [mutableStr mutableCopy];
        NSLog(@"%p",MutableStrMutableCopy1);
        
        NSMutableString *MutableStrMutableCopy2 = [mutableStr mutableCopy];
        NSLog(@"%p",MutableStrMutableCopy2);
        
        NSString *MutableStrMutableCopy3 = [mutableStr mutableCopy];
        NSLog(@"%p",MutableStrMutableCopy3);
        
        NSMutableString *MutableStrMutableCopy4 = [mutableStr mutableCopy];
        NSLog(@"%p",MutableStrMutableCopy4);
     
    

    控制台输出如下

    2016-12-22 15:13:45.732 CopyAndStrong[16356:430316] 0x10e0fa098
    2016-12-22 15:13:45.732 CopyAndStrong[16356:430316] 0x60000006e240
    2016-12-22 15:13:45.733 CopyAndStrong[16356:430316] 0x600000071ac0
    2016-12-22 15:13:45.733 CopyAndStrong[16356:430316] 0x618000072740
    2016-12-22 15:13:45.733 CopyAndStrong[16356:430316] 0x610000071dc0
    2016-12-22 15:13:45.733 CopyAndStrong[16356:430316] 0x608000070dc0
    

    类似不可变字符串的mutableCopy


    总结:
    1. copy产生不可变字符串,mutableCopy产生可变字符串;
    2. 只要mutablecopy就会开辟空间, copy可变字符串才会开辟空间;
    答: 为什么要用 copy 修饰 NSString

    如果用 NSString 强引用一个 NSMutableString ,他们实际都是指向同一个NSMutableString , 而一旦NSMutableString的值改变,那么所谓的NSString也随之改变

    相关文章

      网友评论

        本文标题:关于copy、mutableCopy的讨论(1)

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