iOS开发详细解析copy和mutableCopy

字数 699阅读 149

在日常开发中,很多时候都会用到copy和mutableCopy,但是大家是否真正了解copy过程中内存发生了什么?copy是深拷贝还是浅拷贝呢?什么时候用copy?什么时候用mutableCopy?有什么区别?

探索前我们需要知道

浅复制:仅仅是拷贝指向对象的指针,并不拷贝对象本身(左图)

深复制:直接拷贝整个对象内存到另一块内存中(右图)

Keynote画的....

注意:使用copy/mutableCopy,类必须实现NSCopying协议/NSMutableCopying协议

我们先看看官方文档怎么说的copy(截取重要的一部分)

The exact meaning of “copy” can vary from class to class, but a copy must be a functionally independent object with values identical to the original at the time the copy was made. A copy produced with NSCopying is implicitly retained by the sender, who is responsible for releasing it....

注意重点(加粗斜体),大概意思为:副本对象必须是一个功能独立的对象,其值与复制时的原始值相同

也就是说:副本对象是独立的,修改源对象/副本对象的属性和行为,不会影响副本对象/源对象.

简单来讲就是copy之后的对象,与源对象互不影响

然后我们要知道copy:创建的是不可变副本(NSString,NSArray,NSDictionary)

mutableCopy:创建的是可变副本(NSMutableString,NSMutableArray,NSMutableDictionary)

接下来是例子:

    NSString *str = @"你好!";
    NSMutableString *mutableStr = [str mutableCopy];
    NSLog(@"%@,%p",str,str);
    NSLog(@"%@,%p",mutableStr,mutableStr);

打印结果:

2018-05-02 11:54:11.415754+0800 demo[2025:206958] 你好!,0x109b75068
2018-05-02 11:54:11.415926+0800 demo[2025:206958] 你好!,0x60c00005ee70

很明显,两个对象的内容一样,但是地址不一样

上面已经说了,copy后的副本对象功能独立,对其修改不能影响源对象,所以理所应当,必须生成一个新的对象.

难道每次都会生成一个新的对象么?每次都是深拷贝么?

当然不是,我们再看一个例子:


    NSString *str1 = @"你好!";

    NSString*str2 = [str1 copy];

    NSLog(@"%@,%p",str1,str1);

    NSLog(@"%@,%p",str2,str2);

打印结果:

2018-05-02 11:36:20.889907+0800 demo[1983:184598] 你好!,0x1057a1068

2018-05-02 11:36:20.890134+0800 demo[1983:184598] 你好!,0x1057a1068

注意,两个对象的内存地址是一样的,也就是说系统并没有创建一个新对象

分析:当NSString类型的对象(不可变)经过copy后,拷贝出来的对象也是NSString类型,也是不可变的.既然两者都是不可改变的, 那么一定不会互相影响,换句话说一定是功能独立的,所以系统不会产生新的对象了

总结一下,关于copy是深拷贝?浅拷贝?是否创建新的对象?这些都是由程序运行的环境所造成的,并不是一概而论。

推荐阅读更多精彩内容