在iOS开发中我们在使用@property定义属性的时候经常会使用copy属性来个对一个NSString或者NSArray、NSDictionary来进行修饰,然而许多同学只是在别人的代码上看到,学习这样使用。
也有一部分同学是大概了解一点,主要是为了让该对象持有赋值对象的副本,避免被赋值对象在其他地方被修改,造成错误(我也是属于这一类。。),该文章主要是为了提升自己对copy属性的理解,并且区分什么时候使用才正确。
1.为什么要使用copy?
- 因为父类指针可以指向子类对象,使用copy修饰对象的话,无论赋值对象是可变还是不可变的,对象本身持有的都是一个不可变的副本,这样就避免外界的影响。(其实这一个话是有点问题的,用copy修饰的对象如果传入一个不可变对象,其实也只是单纯的指针拷贝,指向的还是同一块内存,但是个人水平有限,对于内存问题不敢妄下定论)
- 如果我们使用strong修饰对象的话,该对象可能会指向一个可变对象,如果这个可变对象发生改变的话,使用strong修饰的对象也会受到影响。
我们在日常使用NSString的时候,为了避免对象在某个地方被改变,而开发者也无法发现这种情况出现,我们经常都是使用copy修饰对象,这个时候即使传入一个“可变”对象,这个时候我们这个NSString 对象持有的只是该“可变”对象的一个“不可变”的副本。
2.在那些地方使用copy
首先这里要区分浅拷贝和深拷贝、集合对象和非集合对象
浅拷贝:一般理解为指针拷贝,就是会拷贝一个新的指针,但是指针指向的内存地址依然保持不变
深拷贝: 可以理解为内容拷贝,也就是说不仅会拷贝一份指针,同时对内容也会进行一次拷贝,相当于复制了一个副本
下面开始区分什么时候回进行浅拷贝,什么时候会进行深拷贝(按照集合类型和非集合类型讨论)
- 对于非集合对象:
操作 | 结果 |
---|---|
[不可变对象 copy] | 浅拷贝 |
[不可变对象 mutableCopy] | 深拷贝 |
[可变对象 copy] | 深拷贝 |
[可变对象 mutableCopy] | 深拷贝 |
就是说我们一般使用copy修饰一个NSString的时候,传入另外一个NSString的时候,只会复制一份新的指针,指向的还是同一个地址。但是由于传入的NSString是一个不可变对象,我们也不用担心它在其它地方被随意更改了。
@property(nonatomic,strong)NSString *strongString;
NSMutableString *mutString = [NSMutableString stringWithString:@"milan"];
self.strongString = [mutString copy];
类似以上操作,用Strong修饰的NSString对象所持有的也是一个"不可变"的副本
- 对于集合类型对象:
操作 | 结果 |
---|---|
[不可变对象 copy] | 浅拷贝 |
[不可变对象 mutableCopy] | 深拷贝 |
[可变对象 copy] | 深拷贝 |
[可变对象 mutableCopy] | 深拷贝 |
注意!对于集合类型的对象,内容拷贝的只有对象本身,对于集合类型内部的元素只进行浅拷贝,就是只拷贝指针
对于在什么地方使用Copy修饰对象,没有硬性要求,理解copy 以及mutableCopy以后,在何处使用自行判断就可以,当然为了避免自己很多时候考虑不周,我们一般建议使用copy修饰实例变量
3.使用copy的注意点
@property (nonatomic,copy)NSMutableArray *mutArray;
NSMutableArray *testArray = [NSMutableArray arrayWithObject:@"milan"];
self.mutArray = [testArray copy];
对于以上的操作在一般使用上是没有问题的,但是当你的mutArray想要插入或删除内容的时候会报错,因为[testArray copy]赋值给mutArray以后,其实它持有的是一个“不可变”的副本,即使你本身定义为一个可变对象。
最后
以上内容是参考别人的东西并加上自己的理解得出的,若有错误之处请指出,并且对于使用copy需要注意的地方,希望有更多的发现
网友评论