使用FBRetainCycleDetector检测引用循环

在iOS开发中,对象之间形成引用循环是一个很大的问题,它会让内存无故被占,甚至还有可能影响通知的接收等。我们在写代码的时候各种小心,但有时候还是避免不了掉入陷阱。下面是几种常见的循环引用示例:

1 . 两个对象通过强引用类型的属性相互持有。

ClassA *aObj = [ClassA new];
ClassB *bObj = [ClassB new];

aObj.b = bObj;
bObj.a = aObj;

2 . 对象通过拥有的Block属性引用自己。

@interface DetailViewController ()
{
    void (^_handlerBlock)();
}
@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _handleBlock = ^{
        NSLog(@"%@", self);
    };
}
@end

这一种情况可以称得上是最隐蔽的了。因为self不一定需要明写,而是通过实例变量隐含地引入。

3 . 通过成为正在运行的定时器的Target而被持有。这种情况可能许多初学者都不太会注意到,比如在一个页面启动定时器后,喜欢在dealloc中写上定时器的invalidate方法。其实只要定时器不停止,该页面就不会销毁,更不会执行dealloc方法。

诸如此类的引用循环还有许多,一不小心就会掉入坑中。在许多时候,我们都可以使用Xcode提供的Instruments检测内存泄漏(Leaks),但这些引用循环导致的内存泄漏有时却被忽略了。为了解决这些问题,Facebook发布了一个叫FBRetainCycleDetector的工具,专门用于检测对象是否存在引用循环。它的使用非常简单,我们可以通过CocoaPods或者直接从GitHub下载源码

pod 'FBRetainCycleDetector'

这个工具能够检测指定对象的引用情况,并把所存在的引用循环中各对象和引用在终端进行打印。

#import <FBRetainCycleDetector/FBRetainCycleDetector.h>

_handlerBlock = ^{
    NSLog(@"%@", self);
};

FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:self];
NSSet *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);

打印结果类似于:

{(
        (
        "-> DetailViewController ",
        "-> _handlerBlock -> __NSMallocBlock__ "
    )
)}

很明显,DetailViewController通过_handlerBlock实例变量引用一个Block对象,而该Block又引用了DetailViewController对象。如果不存在引用循环的话,打印的结果将是空的。



文/戴维营教育(简书作者)
原文链接:http://www.jianshu.com/p/2c7a7c53c91a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值