解决iOS开发中app的内存泄漏

作者: 王方帅 | 来源:发表于2016-07-15 17:25 被阅读682次

    在arc下,xcode已经把大多数内存问题给我们解决了,但是不是所有
    1,block会引起内存泄漏,如果block回调中用到了self的引用,但是没有加_weak 声明,则self将会被block copy到内部增加一次引用计数,形成循环引用。
    例如下面的代码中(如果单例中持有block)self将永远不会被释放。

    [[YYBDatahub sharedInstance] fetch_cardWithComplete:^(id responseObj, NSError *error) {
                [self refreshText];
            }];
    

    解决办法是在工程的constant.h文件中定义一个define:

    #define kCreateWeakSelf __weak __typeof(&*self)weakSelf = self
    

    然后上面的代码修改为

    kCreateWeakSelf;
            [[YYBDatahub sharedInstance] fetch_cardWithComplete:^(id responseObj, NSError *error) {
                [weakSelf refreshText];
            }];
    

    2,delegate声明为strong会造成循环引用,delegate也不能用assign来声明,因为assign可能会造成野指针,应该用weak声明,工程中可能有人习惯用superVC,parentVC等方式来实现delegate类似的功能,这时候要尤其注意。例如:

    @property (nonatomic,weak) id<YYBBirthdaySelectViewDelegate> delegate;
    

    3,有的时候创建一个view会加到windows上,但是最后为了下次不用创建就能使用,所以只将alpha设为0或hidden为YES,没有从windows上移除,这时候就造成了内存泄漏,甚至有的下次没有重用之前创建的view,重复创建,造成view越来越多,泄漏越来越大。
    4,可能有的数据放到了单例中保存,但是没有指定在何种情况下清空保存在单例中的数据,这时候也会造成泄漏。
    5,NSTimer会强引用self,所以用完之后要调用

    [_notificationTimer invalidate];
    

    方法来手动释放对self的强引用
    综上所述,是我目前遇到的arc下所有内存泄漏的情况。
    最后给大家提供一个神器,FBAllocationTracker,facebook出的一款监测alloc,dealloc的工具,
    (1)在main.m中加入

    [[FBAllocationTrackerManager sharedManager] startTrackingAllocations];
            [[FBAllocationTrackerManager sharedManager] enableGenerations];
    

    (2)在首页调用一下获取当前alloc,但未dealloc的类,最后NSLog一下即可看到是否有泄漏的情况。

    NSArray *instances =[[FBAllocationTrackerManager sharedManager] instancesOfClasses:@[
                                                                                             [YYBAlbumChoiceViewController class]];
    

    我是用简便的方式把所有类名批量操作的方式加到了这个里边,监测了app中存在的大部分内存泄漏,可以说是神器。唯一不足的是多个tabbar的时候,FBAllocationTracker监测的不准,监测tabbar没有释放,但实际上我把main.m中关于AllocationTracker的代码注掉后,tabbar是走了dealloc方法的,所以我大胆假设FBAllocationTracker强引用了每个tabbar来实现的监测功能。

    相关文章

      网友评论

      • 高手世界:想问一下,第三种情况什么时候才会遇到呢,能举个例子吗,
      • gmfx:更正一下:第一个例子在block里调用self会不会造成循环引用和这个block是否被这个单例所持有有关
        -(void)fetch_cardWithComplete:(void(^)(id responseObj, NSError *error))block
        {
        //....
        block( ... , ...);
        }
        单例里这样写的代码是不会造成循环引用的
        王方帅:@gmfxch 确实是这样的
      • BetrayalPromise:笔者 我今天6点半起来写了个demo 确实没有循环引用 你用的那个YYDataHud 是YYKit里面的吗
        王方帅:@BetrayalPromise 那个单例是我项目里的,你自己写个单例,写个block,在viewcontroller里调用,在block里写self试试,看viewcontroller的dealloc肯定没走,没走说明没释放
      • BetrayalPromise:提个意见啊 单例一般是由静态指针掌控生命周期的 换句话说 单例从程序运行开始到结束都存在的 这个是不受block copy到堆中操作的影响 在 block中使用单例不会有内存问题 block是作为回调使用 说白了 block中的内容是作为参数的 不会有内存问题 笔者的[YYBDatahub sharedInstance] fetch_cardWithComplete:^(id responseObj, NSError *error) {
        [self refreshText];
        }];
        说有内存问题。这个是不对的
        王方帅:@BetrayalPromise 你理解错了,是单例的block回调里写self.属性名会把self的引用计数加一,这样block和self造成循环引用,block可能是单例里的不释放没关系,但self是viewcontroller,self不释放就有问题了

      本文标题:解决iOS开发中app的内存泄漏

      本文链接:https://www.haomeiwen.com/subject/dzvyjttx.html