FBRetainCycleDetector 0.1.4

FBRetainCycleDetector 0.1.4

测试已测试
语言语言 Objective C++Objective C++
许可证 BSD
发布最后发布2017年11月

Dave LeeGrzegorz PstruchaJeremie Marguerie 维护。



  • 作者
  • Grzegorz Pstrucha

FBRetainCycleDetector

Build Status
Carthage compatible
CocoaPods
License

一个iOS库,使用运行时分析来查找保留循环。

关于

保留循环是创建内存泄漏最常见的方式之一。创建保留循环非常容易,而且往往很难发现。
FBRetainCycleDetector 的目标是帮助在运行时找到保留循环。
此项目的功能受到了 Circle 的影响。

安装

Carthage

将以下内容添加到 Cartfile 中

github "facebook/FBRetainCycleDetector"

FBRetainCycleDetector 是从非调试构建中构建的,因此当您想要测试它时,请使用

carthage update --configuration Debug

CocoaPods

将以下内容添加到 podspec 中

pod 'FBRetainCycleDetector'

您只能在 Debug 构建中完全使用 FBRetainCycleDetector。这是由 编译标志 控制的,可以提供给构建以便在其他配置中使用。

示例用法

让我们快速进入

#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);

- (NSSet*>)findRetainCycles 将返回一组包含封装对象的数组。这最初可能很难看,但让我们来看看。此集合中的每个数组将表示一个保留循环。此数组中的每个元素都封装了此保留循环中的一个对象。检查 FBObjectiveCGraphElement

示例输出可能如下所示

{(
    (
        "-> MyObject ",
        "-> _someObject -> __NSArrayI "
    )
)}

MyObject 通过 someObject 属性保留了它所构成的部分 NSArray

FBRetainCycleDetector 将寻找最长不超过 10 个对象的循环。
我们可以将其做得更大(虽然这将变得更慢!)。

FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCyclesWithMaxCycleLength:100];

过滤器

还可能有我们想要排除的保留循环。这是因为并非每个保留循环都是泄漏,我们可能想要过滤掉它们。
为此,我们需要指定过滤器

NSMutableArray *filters = @[
  FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache"),
];

// Configuration object can describe filters as well as some options
FBObjectGraphConfiguration *configuration =
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:filters
                                     shouldInspectTimers:YES];
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];

每个过滤器都是具有两个 FBObjectiveCGraphElement 对象的块,它们可以声明其关系是否有效。

检查 FBStandardGraphEdgeFilters 了解如何使用过滤器。

NSTimer

NSTimer 可能很麻烦,因为它会保留其目标。这通常意味着保留循环。 FBRetainCycleDetector 可以检测这些,
但如果你想跳过它们,你可以在传递给 FBRetainCycleDetector 的配置中指定这一点。

FBObjectGraphConfiguration *configuration =
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:someFilters
                                     shouldInspectTimers:NO];
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration];

关联

Objective-C 允许我们使用 objc_setAssociatedObject 为每个对象设置关联对象。

这些关联对象在使用保留策略,如 OBJC_ASSOCIATION_RETAIN_NONATOMIC 时,可能会导致保留循环。FBRetainCycleDetector 可捕获这类循环,但要做到这一点,我们需要对其进行配置。在应用程序生命周期早期,最好是在 main.m 中,我们可以添加以下内容:

#import <FBRetainCycleDetector/FBAssociationManager.h>

int main(int argc, char * argv[]) {
  @autoreleasepool {
    [FBAssociationManager hook];
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}

在上面的代码中,[FBAssociationManager hook] 会使用 fishhook 来间接函数 objc_setAssociatedObjectobjc_resetAssociatedObjects,以追踪在创建之前的关联。

获取候选对象

如果您想对应用程序进行性能分析,可能需要一个抽象的方式,以便获取 FBRetainCycleDetector 的候选对象。虽然您可以直接跟踪它,但您也可以使用 FBAllocationTracker。这是我们创建的一个小工具,可以帮助您跟踪对象。它提供简单的 API,您可以查询例如所有给定类的实例,或当前跟踪的所有类名等。

FBAllocationTrackerFBRetainCycleDetector 可以很好地协同工作。我们已经创建了一个小示例和drop-in项目,名为 FBMemoryProfiler,该项目利用了这两个项目。它提供了一个非常基础的 UI,您可以使用它来跟踪所有分配并从 UI 中强制执行保留循环检测。

贡献

请参阅 CONTRIBUTING 文件,以了解如何有所帮助。

许可证

FBRetainCycleDetector 是 BSD 许可的。我们还提供了一个额外的 专利许可