iOS iOS开发FBRetainCycleDetector

FBRetainCycleDetector分析

2016-05-04  本文已影响3575人  c_xiaoqiang

FBRetainCycleDetector是Facebook新开源的一个项目。配合FBMemoryProfiler使用起来也是很方便。当然FBMemoryProfiler里面使用到了FBAllocationTracker。目前第一版,在测试的过程中也会遇到一些crash,相信经过使用者的修改和作者本人的自测,会越来越完善的。这篇文章的目的主要是对于FBRetainCycleDetector内部实现进行一个介绍,单单只会使用总感觉是远远不够的。

文章会分为几个模块进行介绍:

<p id="最简单的使用方法">

最简单的使用方法

最简单的使用方法,不包含Configuration。单纯的去查找一个对象的引用循环

FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:nil];
[detector addCandiate:myObject];
//- (NSSet<NSArray<FBObjectiveCGraphElement *> *> *)findRetainCycles;
NSSet<NSArray<FBObjectiveCGraphElement *> *> *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);

这里先简单的说明一下,findRetainCycles查询方式所使用到的算法是DFS(深度优先搜索)。

<p id="主要元素类及其辅助类的介绍">

主要元素类及其辅助类的介绍(FBObjectiveCGraphElement)

FBRetainCycleDetector所使用到的对象类型是FBObjectiveCGraphElement,会在调用函数:addCandiate的时候内部进行初始化为该对象类型或者其子类。

FBObjectiveCGraphElement

FBObjectiveCGraphElement是所有用来查找对象类型的基类。所有的查找对象都基于它实现。该类并不需要外部的调用,主要是供内部查询使用。其提供的功能主要是:

FBObjectGraphConfiguration

这里先介绍一下Configuration,再去介绍FBObjectiveCGraphElement的子类。FBObjectGraphConfiguration内容很少,其主要提供的是过滤的block类型FBGraphEdgeFilterBlock和过滤器的初始化方法:

    - (instancetype)initWithFilterBlocks:(NSArray<FBGraphEdgeFilterBlock> *)filterBlocks
             shouldInspectTimers:(BOOL)shouldInspectTimers

即传入一个过滤block的数组,该数组会被FBObjectiveCGraphElement对象类型在调用filterObjects的时候一次调用。shouldInspectTimers的作用是是否检查NSTimer。
接下来看看FBGraphEdgeFilterBlock的定义:

typedef FBGraphEdgeType (^FBGraphEdgeFilterBlock)(FBObjectiveCGraphElement *_Nullable fromObject,
                                              FBObjectiveCGraphElement *_Nullable toObject);

传入fromObject(传入的对象)和toObject(被持有的对象),根据自己需求对对象进行处理。添加到数组后进行初始化。这里可以举个例子,过滤掉所有以UINavi开头的对象:

FBGraphEdgeFilterBlock filterBlock = ^(FBObjectiveCGraphElement *_Nullable fromObject,
                                           FBObjectiveCGraphElement *_Nullable toObject){
        if (![[fromObject classNameOrNull] hasPrefix:@"UINavi"]) {
            return FBGraphEdgeValid;
        }
        return FBGraphEdgeInvalid;
    };
FBObjectGraphConfiguration *configuration = [[FBObjectGraphConfiguration alloc]
                                                 initWithFilterBlocks:@[filterBlock]
                                                 shouldInspectTimers:NO];
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration];

这就是一个包含configuration的初始化过程。

FBObjectiveCGraphElement相关子类

上面已经说了,FBObjectiveCGraphElement只提供了对associate object的持有查找。因此其它对象的持有查找是通过子类实现的,主要包含:FBObjectiveCBlock,FBObjectiveCObject,FBObjectiveCNSCFTimer

FBObjectiveCBlock实现

主要的实现内容是:重写父类方法allRetainedObjects,当然也是有调用[super allRetainedObjects]。接下来就是对于block的识别和获取引用关系。最后再封装为FBObjectiveCBlock对象类型。

FBObjectiveCObject实现

在重写以及调用父类方法与block是一样的。不同的地方在于对于持有对象的获取。。

FBObjectiveCNSCFTimer实现

FBObjectiveCNSCFTimer的实现内容比较少,其主要就是通过runloop去获取CFRunLoopTimerGetContext,再对获取到的数据进行处理即可。

<p id="主要的查找类及其辅助类介绍">

主要的查找类及其辅助类介绍(FBRetainCycleDetector)

FBRetainCycleDetector

FBNodeEnumerator

结论

FBRetainCycleDetector目前处于第一版本,因此会有一些bug,但并不会影响正常的使用。虽然查找算法上面有可能会导致比较大的内存消耗(毕竟如果程序够大的话,深搜也是谈不上效率的)。暂时没有对FBMemoryProfiler进行描述的原因是,FBMemoryProfiler主要还是界面的实现以及与FBAllocationTracker功能的结合。 FBAllocationTracker的功能比较简单,后面会用一篇小文章来进行概述。

上一篇下一篇

猜你喜欢

热点阅读