拷贝 在iOS开发中太习以为常了,我们都非常了解了,本篇就再次回顾这个老生常谈的知识点
一、定义
浅拷贝
:拷贝指针,仅拷贝指针地址,对象的内存区域还是一样的,即新的指针也指向同一片内存。
深拷贝
:拷贝内存。即真正的复制了一份,指针地址,内存地址都完全不一样。
那么iOS中是怎么实现深、浅拷贝的?
二、Copy和mutableCopy
是通过Copy
和mutableCopy
来实现的拷贝的
我们知道,若想令自己所写的对象具有拷贝功能,则需实现 NSCopying
协议,如果可变的话,如果定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying 与 NSMutableCopying协议。
系统的NSString
、NSArray
、NSDictionary
就是满足了NSCopying
和协议NSMutableCopying
协议的类,
下面我们就以NSString
和NSArray
分别代表非集合类和集合类为例
非集合类
NSString
-
定义一个NSString变量str1,分别copy和mutableCopy,打印内存地址
image.png
copy后,地址没有变化,mutableCopy后,地址变化了
-
定义一个NSMutableString变量str1,重复上述操作,打印地址
image.png
copy和mutableCopy后,地址都变化了
结论:😄
对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
集合类
NSArray
-
定义一个NSArray对象ar1,分别copy和mutableCopy,打印
image.png
copy后地址没变,mutableCopy后地址改变
那么它内部的元素会变化么?我们更改其中第一个元素,看是否都更改了
image.png
ar1更改可第一个元素,ar2和ar3也同步更新了,说明内部元素只是浅拷贝
-
定义一个NSMutableArray对象ar1,分别copy和mutableCopy,打印
image.png
三个地址完全不同,都是地址拷贝;同时我们更改了ar1的第一个元素,其他数组也同样更新了,也是指针拷贝
结论😄:对 immutable 对象进行 copy,是指针复制, mutableCopy 是内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //单层深复制
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制
到此为止,那我们属性修饰符里用copy、mutableCopy还是strong呢?
三、property修饰符
- 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
- 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
所以
修饰NSString或者NSArray、NSDictionary时,一般使用copy,可以防止setter方法时,使用的是子类(可变对象)赋值,后面更改时,导致数据混乱。
修饰NSMutableString或者NSMutableArray、NSMutableDictionary时,使用strong,这样,才可以进行后面的更改。
网友评论