iOS 控制器POP后dealloc方法不走,通知监听无法移除的问题

11 篇文章 0 订阅

最近项目突然被说会闪退,且无法重现,时有出现。接到问题后一步步排查,终于发现问题。

表现某个页面的通知观察者方法被多次调用!

原因查找:

1、通知的监听这里我写在viewDidLoad里面,多次被调用只能说明多次发送了通知,或者多次添加了观察者。

2、通知的发送确定没多次调用,而通知的监听为何会被多次添加?

3、一般我们会在dealloc方法里面移除通知,打断点发现,dealloc方法并未调用

4、通知每进一次页面添加一次,pop之后又未被移除,那就可能造成内存泄露,闪退!

解决思路也就是要确定dealloc方法为何不走!

dealloc不被调用的原因:

1、ViewController中存在定时器NSTimer,定时器一跑起来就增加了ViewController的return count,如果你不将这个timer invalidate,则控制器无法释放;

2、ViewController中有强引用代理(delegate),改为weak修饰;

3、ViewController中有Block,且有循环引用。这个也是我不能调用dealloc的真正原因。Block体内使用实例变量会造成循环引用,使得拥有这个实例的对象不能释放。 
例如你这个类叫OneViewController,有个属性是NSString *name; block的持有者也是VC的一个属性,如果你在block体中使用了self.name,那样子的话这个类就没法释放。

注意:VC持有的实例变量和@implementation下面创建的全局变量也会被循环引用

@interface GroupChpPay ()
{
    UIView *_xxView;
}
@implementation GroupChpPay
{
    UIView *_xxView;
}

即使在你的block代码中没有显式地出现"self",也会出现循环引用!就像上面的实例变量和全局变量,并不会使用self.调用,其实也会被循环引用。只要你在block里用到了self所拥有的东西!

但对于这种情况,我们无法通过加__weak声明或者__block声明去禁止block对self进行强引用或者强制增加引用计数。但我们可以通过指针来避免循环引用,具体是这么做的:

__weak typeof(self) weakSelf = self;
self.blkA = ^{
    __strong typeof(weakSelf) strongSelf = weakSelf;//加一下强引用,避免weakSelf被释放掉
    NSLog(@"%@", strongSelf->_xxView); //不会导致循环引用.
};


排查方法:

1、在添加通知的页面搜索所有 ^ 符号,也就是排查所有block方法有没有使用弱引用。基本都改好之后,dealloc方法可以被调用了,控制器销毁通知成功移除,问题解决!

2、真找不到哪里出错,最笨的方法,将可能出错的代码一段段注释排查!

还有值得一提的是,一般编译器会对需要使用weak弱引用的地方给出警告,但我这里没有警告,是在环信的SDK写的类里面,坑。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值