关于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,他依然还是静静地在常量区做一个字符串常量

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也随之改变

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容