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

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

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声明可变字符串。

目录
相关文章
|
iOS开发
iOS block修饰符用copy还是strong
iOS block修饰符用copy还是strong
149 0
你知道block循环引用怎么解决了吗?
在使用block的时候,最需要注意的问题便是循环引用,这节主要讲解,block是如何产生的?碰到循环引用又该怎么解决。
171 0
你知道block循环引用怎么解决了吗?
iOS-底层原理 10:strong&copy&weak底层分析 以及 方法签名和attribute简写含义
iOS-底层原理 10:strong&copy&weak底层分析 以及 方法签名和attribute简写含义
166 0
iOS-底层原理 10:strong&copy&weak底层分析 以及 方法签名和attribute简写含义
|
iOS开发
iOS开发:block死循环及__weak弱引用提前释放的问题解决
block死循环及__weak弱引用提前释放的问题解决
323 0
|
存储 iOS开发
iOS - weak 与 assign 的区别,weak自动置nil
weak和assign是一种“非拥有关系”的指针,通过这两种修饰符修饰的指针变量,都不会改变被引用对象的引用计数。但是在一个对象被释放后,weak会自动将指针指向nil,而assign则不会。