iOS 内存泄漏整理

最近我们app感觉内存暴涨,肯定是有了内存问题。经过几天奋战整理了成吨的内存泄漏点,每一种抽一个代表出来作为记录。

这个博客还有别的案例: http://blog.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/

1,JTNavigationController 中的循环引用
github issue:  https://github.com/JNTian/JTNavigationController/issues/30
关键代码:
- (void)setJt_navigationController:(JTNavigationController *)navigationController {
    objc_setAssociatedObject(self, @selector(jt_navigationController), navigationController, OBJC_ASSOCIATION_ASSIGN); // OBJC_ASSOCIATION_RETAIN => OBJC_ASSOCIATION_ASSIGN
}

2,有 presentViewController 没有对应的 dismissViewController

// 如果是 present 出来的,必须 dismiss,不然会有内存泄漏
    __weak typeof(self) wself = self;
    [selfdismissViewControllerAnimated:YEScompletion:^{
        [wself _showLoginController];
    }];

3,delegate 写成了 strong 
 
    
// @property (nonatomic, strong) id delegate;
@property (nonatomic, weak) id delegate;

4, NSPointerArray 弱指针使用不当 
 
    
- (NSPointerArray *)listeners {
    if (!_listeners) {
        // _listeners = [[NSPointerArray alloc] init];
        _listeners = [NSPointerArrayweakObjectsPointerArray];
    }

    return _listeners;
}

5,定时器没有关闭
这里是一个在后台循环刷票据的定时器,注销之后定时器依旧活跃(每次)
解决方案是注销之后把定时器关掉。
 
    
- (void)_beginRefreshToken {
    AccountManager* accountManager = [AccountManager sharedInstance];
    if ([accountManager isGuestMode]) {
        // 游客模式不需要刷新票据return;
    }

    if (!self.refreshTicketTimer) {
        self.refreshTicketTimer = [NSTimerscheduledTimerWithTimeInterval:kRefreshTicketInterval
                                                                  target:self
                                                                selector:@selector(_onRefreshTicketTimer:)
                                                                userInfo:nil
                                                                 repeats:YES];
    }
}

6,block 循环引用
这里的例子是, GuideViewController 引用了 LicenseViewController,LicenseViewController 引用了 acceptHandler 
而 acceptHandler 又捕获并强引用了 GuideViewController  
更多详细例子和解决方案可以参考这个博客
- (void)_loadLicenseView {
    LicenseViewController* controller = [[LicenseViewController alloc] initWithNibName:nilbundle:nil];
    [selfaddChildViewController:controller];

    __weak __typeof(self) wself = self;
    controller.acceptHandler = ^{
       //  [self _finishGuide];
        [wself _finishGuide];
    };
}

关于 block 循环引用问题,我们定义了两个公用的宏:
#define YYWeakSelf(wself)             __weak   __typeof(self)  wself = self
#define YYStrongSelf(sself, wself)    __strong __typeof(wself) sself = wself



你可能感兴趣的:(objective-C)