前言
在代理模式中,属性通常写成如下形式
@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里写了一个协议
- 有一个代理属性
- Baby.m
- 假设用retain修饰的情况
- 并重写了delegate的setter and getter
- Nanny.h
- Nanny里有一个Baby属性
- Nanny.m
- 重写了Baby的setter and getter
- 为了方便分析问题
- main.h
分析
- 根据内存管理的原则,谁持有对象,那谁就有责任将其释放
- 当各自的引用计数由1到0时,会调用dealloc方法。
- 但是他们此时他们互相持有,导致最后谁都得不到释放。
- 过度释放
总结
希望通过这个例子,能让大家对于内存管理有更深刻的理解。
网友评论