copy和strong的区别及使用不当引起的crash

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/jia12216/article/details/97273089

copy属性用在需要深拷贝的地方,如:block属性。它会造成内存增加,使用不当会造成拷贝异常而崩溃。strong属性用在需要浅拷贝,只要指向它的所有对象不都被释放,用它声明的属性对象就不会被释放。如:对象属性。
1.数据源为可变字符串而言,使用copy申明属性,会开辟一块新的内存空间存放值,源数据不论怎么变化,都不会影响copy属性中的值,属于深拷贝;使用strong申明属性,不会开辟新的内存空间,只会引用源数据内存地址,因此源数据改变,则strong属性也会改变,属于浅拷贝。
在响应式编程的开发模式下,为了保持数据的一致性,通常对NSMutableString等可变类型属性仍旧使用strong声明。响应式编程的数据处理过程式,从服务接收到消息(加密的json字符串),经过app网关(网络请求组件)进行解密,消息统一,转换为字典;然后经过view-model进行数据预先处理转换具体实体类;然后传递到view层进行数据展示。在消息传递过程中可能对原始数据进行修改,为了保证数据的唯一性,所以最好用strong声明。
当然在mvc建构时通常数据解析是在UIViewController直接解析的,所以不存在数据传输过程,可能使用copy声明更合适。
源对象为不可变字符串而言,不论使用copy还是strong属性,所对应的值是不发生变化,strong和copy并没有开辟新的内存,即并不是深拷贝。此时,使用copy或是strong,并没有对数据产生影响。
2.源对象为不可变字符串而言,不论使用copy还是strong属性,所对应的值是不发生变化,strong和copy并没有开辟新的内存,即并不是深拷贝。此时,使用copy或是strong,并没有对数据产生影响。
3.属性为可变数组、可变字典copy申明的可变数据,初始化或复值之后,变成不可变数组,对数组执行增,删会跑出错误。这是因为copy属性修饰后,在初始化或赋值时,会先执行copy操作,然后赋值。
由于一个对象的block可以在多个对象中注册,所以要用深拷贝,就是要用copy声明。不能用strong声明。当然这个block只在最后一个注册的对象中生效。
下面是使用copy声明对象,引起无法识别对象崩溃的具体例子。崩溃的原因是:copy声明的对象变量只能对基本对象或block进行深拷贝,若是自定义对象不实现NSCoding协议(序列和反序列化)并声明为copy类型就会发生这种不测!
在这里插入图片描述
在这里插入图片描述
可以看到self.alvEntity有内存地址,但是它的ai属性为nil,结果由于它是用copy声明的,结果在执行self.alvEntity.ai = ai;命令进行深拷贝时崩溃了。解决方案很简单:@property (nonatomic, strong) AddressInfo *ai;
所以要了解copy和strong的区别,合理使用。简言之:block属性全用copy,其它全用strong。当然你有特别要求,对可变字符串数据源,关注跟踪整个数据的变化过程,不关注数据一致性,不关注内存的那点增加,那么你可以使用copy声明可变字符串。

猜你喜欢

转载自blog.csdn.net/jia12216/article/details/97273089