ARC下的内存泄漏

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
    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 那一列的个数有没有连续增加,如果连续增加,那么说明出现循环引用了,注意:此方法只适用于真机。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值