OC的copy与mutableCopy剖析(copy篇)

来源:互联网 发布:excel下拉菜单选择数据 编辑:程序博客网 时间:2024/06/07 21:50

提示:OC中的字符串有NSString(不可变)和NSMutableString(可变)两类,其中后者是前者的子类。本文通过分析不同种类字符串的内存地址以及对象方法得出copy、mutableCopy的相关特性

copy篇:
我们知道一个NSString类型的字符串可能会位于内存的常量区,堆区或者棧区(详情请参考博文Mac下NSString(不可变字符串)内存分析)
图一
字符串str1,str2,str3都是不可变字符串,分别调用[str1 copy]、[str2 copy]、[str3 copy]后,通过比较它们的地址,我们得出结论:
对于一个不可变的字符串,无论它在内存的那个区,调用copy方法,它返回的都是该字符串本身,同样是不可变的字符串(指针指向同一个地方)
图一
这里有一点需要提醒大家注意的是,在NSObject的头文件里,copy以及mutableCopy它返回的均是一个id类型,并不是一个字符串类型。
图二

copy注意点1:
我们声明一个NSMutableString 的指针变量 str
图片三
编译器认为str指向的是一个可变字符串对象,具有appendFormat方法,因此在XCode编译的时候不会报错或者给出警告,但实际上这块内存地址是不可变的,所以一旦运行程序,调用appendFormat方法(运行时方法动态检测)就会曝出错误:unrecognized selector sent to instance 0x6d6f7435
这里写图片描述
而这个0x6d6f7435地址就是我们不可变字符串str2的地址

copy注意点2:
我们生成一个NSMutableString字符串
这里写图片描述
str是一个可变的字符串,可以调用appendFormat方法。而此时str1是不能调用的。一旦调用该方法,虽然编译没有问题,但在运行时就发生一个同样的错误:unrecognized selector sent to instance 0x6d6f7435。这是因为[str copy],虽然str是一个可变的字符串,但是我们会发现它返回的地址是另外一个地址。这个地址可能是棧区,也可能在堆区,无论在哪里都不允许改变。
这里写图片描述

总结:
1.当不可变对象调用copy的时候,只是拷贝了指针,指向内存中的同一个地址(浅拷贝,对象的retainCount+1)
2.当可变对象调用copy的时候,会生成不同的空间(深拷贝,对象的retainCount不变)
3.copy返回的类型都是不可变的,给这个不可变的地址发送一个类似appendFormat的方法,尝试改变里面的内容。即使通过了编译,瞒过了XCode,在运行的时候会报出unrecognized selector sent to instance Address的错误

好的idea来自思想的交流和碰撞!

0 0
原创粉丝点击