美文网首页ios 知识小集OC内存iOS性能监测、优化
iOS杂谈:影响控制器正常释放的常见问题

iOS杂谈:影响控制器正常释放的常见问题

作者: 明仔Su | 来源:发表于2016-03-04 12:49 被阅读5344次

    引言

    iOS开发中内存管理是很重要的,如果处理不当,轻则会导致内存泄漏、莫名其妙的bug等等,重则可能导致程序崩溃。本文总结了在iOS开发中三个可能导致控制器不能正常释放的常见问题。

    导致控制器不能正常释放的原因?

    控制器的引用计数不为0,也就是说被其他对象强引用,因此不能正常释放。

    如何知道控制器是否已经正常释放?

    在ARC模式下,控制器在彻底销毁之前会调用dealloc方法,并自动调用[super dealloc]方法。因此,可以重写基类的dealloc方法,输出控制器销毁提示信息,如果控制器没有调用dealloc方法,说明不能正常释放。

    - (void)dealloc {
        NSLog(@"%@ dealloc",NSStringFromClass([self class]));
    }
    

    问题一:block引发的循环引用

    无弱引用声明的情况下,block持有它里面所有对象的所有权,即为强引用,所以当在block里面使用self的时候,可能会导致控制器不能正常释放。

    比如:objectB拥有callbackBlock属性,在objectA中设置该属性

    [objectB setCallbackBlock:^{
        [self excuBlock];
    }];
    

    在block中引用了自身方法(或变量),形成了循环引用。

    解决方法:

    在block中使用对自身对象的弱引用来替换self

    __weak typeof(self) weakSelf = self;
    
    [objectB setCallbackBlock:^{
    
        [weakSelf excuBlock];
    
    }];
    

    如果在block使用了成员变量,也要使用其弱引用,以 _dataSource为例:

    __weak typeof(_dataSource) weakDataSource = _dataSource;
    

    问题二:强引用的delegate引发的循环引用

    如果一个delegate属性的声明是strong的时候,会持有自身控制器的所有权,导致控制器不能正常释放。

    比如:

    CustomView的delegate声明

    @property (nonatomic, strong) id<WZDelegate> delegate;
    

    在控制器中赋值

    self.customView.delegate = self;
    

    这样,造成self对customView强引用,customView对self强引用,引发循环引用。

    解决方法:

    对代理使用弱引用

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

    问题三:使用了NSTimer没有销毁

    当我们使用NSTimer的方法

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
    

    时,定时器对象会对它的target(即self:当前控制器)持有强引用,如果定时器不销毁,则控制器无法释放。

    解决方法:

    - (void)viewWillDisappear:(BOOL)animated或者- (void)viewDidDisappear:(BOOL)animated或者其他确定离开当前控制器的方法中销毁定时器。

    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
        if (self.timer != nil) {
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    

    相关文章

      网友评论

      • Vincent20481:最近使用MJ刷新,在刷新Block中必须弱引用,否则也会导致控制器不释放
        Vincent20481:@温柔vs先生 会,你可以试一试
        温柔vs先生:这个不会吧
      • feca61443dfa:现在我创建一个控制器,pop后不走释放,当重新push进去后就释放了,这是什么问题
        可可_running:pop后没有释放说明有对象持有,重新push后释放说明VC被重新赋值了,所以之前的VC没有对象持有就被释放了
        雷鸣1010:@猫佐拉 将相关属性设置为weak 或者assign 就可以了,是block里面有循环引用
      • 谢谢生活:还有头文件相互引用问题,通知移除问题,
        东健FO_OF:头文件不会,import会避免这个

      本文标题:iOS杂谈:影响控制器正常释放的常见问题

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