iOS中的循环引用
1. 概述
iOS内存中的分区有:堆、栈、静态区。其中,栈和静态区是操作系统自己管理回收,不会造成循环引用。在堆中的相互引用无法回收,有可能造成循环引用。
循环引用的实质:多个对象相互之间有强引用,不能施放让系统回收。
解决循环引用一般是将 strong 引用改为 weak 引用。
2. 循环引用场景分析及解决方法
1)父类与子类
如:在使用UITableView 的时候,将 UITableView 给 Cell 使用,cell 中的 strong 引用会造成循环引用。
1 | // controller |
解决:strong 改为 weak
1 | // cell |
2)block
block在copy时都会对block内部用到的对象进行强引用的。
1 | self.testObject.testCircleBlock = ^{ |
self将block作为自己的属性变量,而在block的方法体里面又引用了 self 本身,此时就很简单的形成了一个循环引用。
应该将 self 改为弱引用
1 | __weak typeof(self) weakSelf = self; |
在 ARC 中,在被拷贝的 block 中无论是直接引用 self 还是通过引用 self 的成员变量间接引用 self,该 block 都会 retain self。
- 快速定义宏
1 | // weak obj |
3)Delegate
delegate 属性的声明如下:1
@property (nonatomic, weak) id <TestDelegate> delegate;
如果将 weak 改为 strong,则会造成循环引用
1 | // self -> AViewController |
4)NSTimer
NSTimer 的 target 对传入的参数都是强引用(即使是 weak 对象)
解决办法: 《Effective Objective-C 》中的52条方法
1 | #import <Foundation/Foundation.h> |
使用方式:
1 | __weak ViewController * weakSelf = self; |
计时器保留其目标对象,反复执行任务导致的循环,确实要注意,另外在dealloc的时候,不要忘了调用计时器中的 invalidate方法。