###循环引用(Retain Cycle)
这里分三种情况讨论:
-
Delegate
我们在使用代理设计模式的时候,一定要注意将 delegate 变量声明为 weak 类型,像这样
@property (nonatomic, weak) id delegate;
-
Block
Block 循环引用也很常见,假设 self 代表当前 ViewController,那么一般写法是这样:
1 2 3 4
__weak typeof(self)weakSelf = self; self.completionHandler = ^{ NSLog(@"%@", weakSelf); };
当然 Block 循环引用其实有很多东西可以讲,我后边会专门写一篇来介绍 Block。
-
NSTimer
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
如果在一个 ViewController 里创建了一个定时器,并且 repeats:值为 YES,一定记得在 pop/dismiss 当前 ViewController 将 timer 设为 invalidate,否则 会造成循环引用,这里要特别需要 注意 的一点是:我们不要在 ViewController 的 dealloc 方法里调用[timer invalidate];
因为从来不会调到这里,我们应该在 viewWillDisappear里边调用,像这样:1 2 3 4 5 6
- (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; if ([self isMovingFromParentViewController]) { [timer invalidate]; //解除对self的引用 } }
CoreFundation/CoreGraphics 相关函数
ARC 针对的 Objective-C 对象来说的,而 CoreFundation/CoreGraphics 这种非Objective-C对象,我们一定要记得自己手动释放,否则会造成内存泄漏
比如:
CGBitmapContextCreate(, , , , , , )
一定要与
CGImageRelease(CGImageRef image)
成对出现。
只要记住一点:CG/CF 开头的函数,有创建就要有释放,这样可以有效降低内存泄漏的风险。
检测内存泄漏的方法
开发应用程序,内存泄漏不可避免,那么如何检测内存泄漏呢,那就要说道 Xcode工具套件中的 Instruments。针对 内存泄漏,主要是两个 Allocations 和 Leaks
这里有篇教程写的比较详细:http://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode
我建议大家直接看英文原版吧,也不难。这里主要说明几点:
-
教程中用的 Instruments 界面跟目前最新的略微有些差别,比如 里边 提到的处于左边的 Mark Heap 按钮,目前改为了 Mark Generation ,在这里:
-
文中的样例,调用的 flickr api url的开头改为
https://
,并且需要翻墙才可以访问。 -
对于 循环引用 如何进行检测
简单点可以通过在对应的类中复写 dealloc 方法,像这样:
1 2 3
- (void)dealloc{ NSLog(@"=== %@ dealloced! ===", NSStringFromClass([self class])); }
如果调用这里,说明不存在循环引用。
同样,我们也可以通过 Instruments 来检测,利用 Allocations ,如图:
这里以 ViewController 为例,在搜索框中输入想要查看的类名,然后连续进行 pop/push 操作,看 #Total 那一列的个数有没有连续增加,如果连续增加,那么说明出现循环引用了,注意:此方法只适用于真机。