代理模式中delegate属性为assign的原因
2016-08-08 本文已影响238人
Bestmer
前言
在代理模式中,属性通常写成如下形式
@property (nonatomic, assign) id<实现的某个协议名称>delegate;
究其背后的原因为什么不使用retain来修饰,其实这里涉及到了内存管理中的循环引用问题。
举个例子
- 对象a创建并引用了对象b
- 对象b创建并引用了对象c
- 对象c创建并引用了对象b
此时b的引用计数为2,a和c的引用计数为1
- 假设a不在使用b,调用release释放了b
- 因为c还在使用b,所以b得引用计数为1,b不会被释放
- 而此时c的引用计数为1,也不会被释放
- 从此,b和c永远留在了内存中,造成了内存泄漏。
- 所以,针对这种情况,我们要避免循环引用,这就是为什么代理模式中属性使用assign而不是retain的根本原因。
在举个例子
- 先创建两个类,Baby和Nanny
- Baby.h
- Baby里写了一个协议
- 有一个代理属性
![](https://img.haomeiwen.com/i2252386/ed686b94a4f81373.png)
- Baby.m
- 假设用retain修饰的情况
- 并重写了delegate的setter and getter
![](https://img.haomeiwen.com/i2252386/1aaa9a72bb972450.png)
- Nanny.h
- Nanny里有一个Baby属性
![](https://img.haomeiwen.com/i2252386/2637dc70cca89c6a.png)
- Nanny.m
- 重写了Baby的setter and getter
- 为了方便分析问题
![](https://img.haomeiwen.com/i2252386/194c8c93e32f8b1a.png)
- main.h
![](https://img.haomeiwen.com/i2252386/093f5a67f93eb54f.png)
分析
- 根据内存管理的原则,谁持有对象,那谁就有责任将其释放
- 当各自的引用计数由1到0时,会调用dealloc方法。
- 但是他们此时他们互相持有,导致最后谁都得不到释放。
- 过度释放
总结
希望通过这个例子,能让大家对于内存管理有更深刻的理解。