您的位置:首页 > 其它

ARC下的内存泄漏

2016-03-14 10:03 260 查看


ARC概念:


ARC全称叫 ARC(Automatic Reference Counting)。在编译期间,编译器会判断对象的使用情况,并适当的加上retain和release,使得对象的内存被合理的管理。所以,从本质上说ARC和MRC在本质上是一样的,都是通过引用计数的内存管理方式。ARC
的出现大大节省了程序员手动管理内存的时间成本,But,世上没有完美的事物,我们也不要把任何事想的那么美好,在 ARC 环境下如果不注意的话也会引起内存泄漏。

###循环引用(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
45
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。针对 内存泄漏,主要是两个 AllocationsLeaks
这里有篇教程写的比较详细: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 那一列的个数有没有连续增加,如果连续增加,那么说明出现循环引用了,注意:此方法只适用于真机。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: