关于copy、mutableCopy的讨论(1)

问: 为什么要用 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,他依然还是静静地在常量区做一个字符串常量

关于copy、mutableCopy的讨论(1)_第1张图片
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,参考如下截图

关于copy、mutableCopy的讨论(1)_第2张图片
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,结果都是同一个地址,而且这里打印出来的地址有点奇怪,我在控制台看到如下描述:

关于copy、mutableCopy的讨论(1)_第3张图片
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))