资讯专栏INFORMATION COLUMN

FBMemoryProfiler 基础教程

kuangcaibao / 1702人阅读

摘要:博文链接基础教程是开源的一款用于分析内存使用和检测循环引用的工具库。在上一篇译文在上自动检测内存泄露中,讲解了的核心原理。在创建的文件中添加之后,运行即可。对于你确信没有问题或者不想修改的问题,你可以在中直接过滤掉。

博文链接:FBMemoryProfiler 基础教程

FBMemoryProfiler是Facebook开源的一款用于分析iOS内存使用和检测循环引用的工具库。

在上一篇[译文]在iOS上自动检测内存泄露中,Facebook讲解了FBMemoryProfiler的核心原理。鉴于有人在评论里问怎么使用,我这里就简单介绍一下。

安装 CocoaPods

建议使用Cocoapods安装,只需要在pod文件中,添加这么一句就行:

pod "FBMemoryProfiler"

FBMemoryProfiler最低支持iOS8,所以如果你的pod文件上最低要求是6或者7的话,是无法直接安装的。所以,建议在开发分支或者如果你有多个target的话,在开发的target上添加FBMemoryProfiler,在生产的target上不需要添加FBMemoryProfiler

我一般习惯于有两个target,一个用于开发,里面可能会包含Reveal、蒲公英等的库,而这在生产包中是不必要的,另一个用于生产,只用于打生产包。

所以我的pod文件可能是这样的:

# Uncomment this line to define a global platform for your project
platform :ios, "8.0"
# Uncomment this line if you"re using Swift
# use_frameworks!

target "FBMemoryProfilerTest" do

end

target "FBMemoryProfilerTest_Dev" do
pod "FBMemoryProfiler"
end

安装成功之后,打开对于的.xcworkspace文件即可。

Carthage

如果你的app从iOS8开始支持的话,你可以使用Carthage来安装。

在创建的Cartfile文件中添加:

github "facebook/FBMemoryProfiler"

之后,运行carthage update --configuration Debug即可。

因为我的app要从iOS6开始支持,所以我没有使用这个。

嵌入代码

首先,要在main.m中添加FBRetainCycleDetector的hook,同时,也要开启FBAllocationTracker的生成追踪:

#import 
#import "AppDelegate.h"

#if DEBUG
#import 
#import 
#endif

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
#if DEBUG
        [FBAssociationManager hook];
        [[FBAllocationTrackerManager sharedManager] startTrackingAllocations];
        [[FBAllocationTrackerManager sharedManager] enableGenerations];
#endif
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

我习惯于添加一个DEBUG标识符,只在Debug状态才开启FBMemoryProfiler。当然,你可以不需要。

之后,我们要在AppDelegate.mapplication: didFinishLaunchingWithOptions:中嵌入FBMemoryProfiler的创建代码:

#if DEBUG
#import 
#import 
#import "CacheCleanerPlugin.h"
#import "RetainCycleLoggerPlugin.h"
#endif

@interface AppDelegate ()
{
#if DEBUG
    FBMemoryProfiler *memoryProfiler;
#endif
}
@end

@implementation AppDelegate

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

#if DEBUG
    memoryProfiler = [[FBMemoryProfiler alloc] initWithPlugins:@[[CacheCleanerPlugin new],
                                                                  [RetainCycleLoggerPlugin new]]
                              retainCycleDetectorConfiguration:nil];
    [memoryProfiler enable];
#endif
    
    return YES;
}

@end

其中,插件是可以不开启的,如果你不想开启的话,你可以这么写:

FBMemoryProfiler *memoryProfiler = [FBMemoryProfiler new];
[memoryProfiler enable];

插件主要是用来进行过滤、去重或者输出、存储等操作的,毕竟如果不开启插件的话,只能通过在手机、模拟器上点击屏幕来看内存泄露,而如果自定义log插件的话,可以将捕获到的内存泄露输出到控制台或者文件中。

比如说,我们可以自定义一个RetainCycleLoggerPlugin,使用FBMemoryProfilerPluggable协议,重写memoryProfilerDidFindRetainCycles:方法:

-(void)memoryProfilerDidFindRetainCycles:(NSSet *)retainCycles
{
    if (retainCycles.count > 0)
    {
        NSLog(@"
retainCycles = 
%@", retainCycles);
    }
}

FBRetainCycleDetector找到循环引用之后,就会调用到上面的方法,但是,retainCycles可能是个空集合,所以这里可以过滤一下。

我在测试我的app的时候,发现这样一个问题:

我确信这里没有因为我而导致的循环引用,但是FBRetainCycleDetector在这里检测到了这个环,这里的主要问题在于_subviewCache,这是苹果的机制,但是并不会造成内存泄露。对于这种情况,我们需要将它过滤出去。

除此之外,还有一个Timer的问题,因为一般情况下,Timer会强引用target,所以可能导致内存泄露,如果你确信没有问题的话,可以关闭对Timer的检测。

过滤代码类似于这种:

NSArray *filters = @[FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache")];
    
FBObjectGraphConfiguration *configuration =
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:filters
                                     shouldInspectTimers:YES];

memoryProfiler = [[FBMemoryProfiler alloc] initWithPlugins:@[[CacheCleanerPlugin new],
                                                                  [RetainCycleLoggerPlugin new]]
                               retainCycleDetectorConfiguration:configuration];
[memoryProfiler enable];

我们只需要设置一个过滤数组,然后添加到FBMemoryProfilerConfiguration中即可。

对于你确信没有问题或者不想修改的问题,你可以在Configuration中直接过滤掉。

比如:

NSArray *filters = @[FBFilterBlockWithObjectIvarRelation([UIPanGestureRecognizer class], @"_internalActiveTouches")];

如果你有CI的需要,你可以在代理中输出log到文本,之后传出到服务器上。

运行

具体操作可以参考Facebook的视频,上一篇译文中也有给出。

操作视频

代码

上面说到的代码放在了这个demo中:

https://github.com/Forkong/FBMemoryProfilerDemo

git clone 之后需要 pod install 一下,才可以运行。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/16219.html

相关文章

  • [译文]在iOS上自动检测内存泄露

    摘要:追踪内存泄露的根源。为此,在我们的开发周期上,我们可能无法尽可能早的定位和修复内存泄露问题。自动化可以在不需要更多开发者的情况下,更快的找到内存泄露。 博文链接:http://ifujun.com/yi-wen-zai-iosshang-zi-dong-jian-ce-nei-cun-xie-lu/原文链接:https://code.facebook.com/posts/5839463...

    miguel.jiang 评论0 收藏0
  • teliute.org 基础教程

    摘要:提供童鞋制作的计算机方面的各种入门教程,教程图文并茂,讲解细致,非常适合初学者入门参考。除特别说明之外,所有教程均采用自由文档许可证版本或更高版本授权。teliute.org 提供TeliuTe童鞋制作的计算机方面的各种入门教程,教程图文并茂,讲解细致,非常适合初学者入门参考。 showImg(http://segmentfault.com/img/bVcag7 src=https://s...

    wums 评论0 收藏0
  • Spring Cloud Alibaba与Spring Boot、Spring Cloud之间不得不

    摘要:下表整理了目前的版本与版本的兼容关系还未所以,不论您是在读我的基础教程基础教程还是正在连载的系列教程。 这篇博文是临时增加出来的内容,主要是由于最近连载《Spring Cloud Alibaba基础教程》系列的时候,碰到读者咨询的大量问题中存在一个比较普遍的问题:版本的选择。其实这类问题,在之前写Spring Cloud基础教程的时候,就已经发过一篇《聊聊Spring Cloud版本的...

    feng409 评论0 收藏0
  • Java入门基础知识点总结(详细篇)

    摘要:深入理解数据库管理系统通用知识及数据库的使用与管理。为后台开发打下坚实基础。项目文档,项目规范,需求分析,数据库设计,工程构建,需求评审,配置管理,修复,项目管理等。 很多新手在学习java的时候都比较迷茫,不知道从哪里开始学起,这里就给大家整理了一份java开发学习路线,比较系统全面,可参...

    shinezejian 评论0 收藏0
  • Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步

    摘要:下面通过这篇,详细介绍当使用作为配置中心之后,如何实现中修改规则同步到。关于下面改造的原理和分析可以见上一篇中修改规则同步到的头两节内容,这里不重复介绍了。但是由于考虑到与的结合使用,略作修改。主要就是中存储配置的和不要弄错。 上一篇我们介绍了如何通过改造Sentinel Dashboard来实现修改规则之后自动同步到Apollo。下面通过这篇,详细介绍当使用Nacos作为配置中心之后...

    Rocko 评论0 收藏0

发表评论

0条评论

kuangcaibao

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<