快速定位没有调用dealloc的问题

前言

视图控制器在退出的时候没有走dealloc,是因为当前控制器被某个对象强引用了,在控制器pop的时候引用计数没有减为0,系统无法帮你释放这部分内存;我在leaks里面去运行,也没有发现内存泄漏的提示,这种对于我们内存优化这个点,肯定是过不去的,也是不允许的;接下来说说出现这个问题的三种情况!

1.block的循环引用问题

大多数的泄露都是block的循环引用引起的。self是retain类型,会使引用计数加一,如果self又强持有这个block,那循环引用就产生了。看下面的示例代码:

self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshBlock:^{

         [self request];

}];

上面的示例,self持有了这个block,在块里面又持有了self,这样会形成一个保留环,导致循环引用。我们可以通过弱引用优化这部分代码:

__weak typeof(self) weakSelf = self;

self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshBlock:^{

         [weakSelf request];

}];

这样就解决了循环引用,就不会存在内存泄露了。这里多说一句,并不是所有的block中有必须要使用weakSelf这种弱引用。如果self并不持有该block,就不会有循环引用的问题,放心大胆的用self就行了。

2.使用strong 修饰属性delegate

@property(nonatomic,strong) id delegate;

注意:这个属性需定义成weak,而非strong,因为本对象与委托对象之间必须为“非拥有关系”(nonowing relationship)。如果声明属性的时候用strong将本对象与委托对象之间定为“拥有关系”,那么就会引入“保留环”。

3.NSTimer

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f

                                                                                    target:self 

                                                                                selector:@selector(someMethod) 

                                                                                userInfo:nil 

                                                                                 repeats:YES];

target引用了self,如果在对象销毁的时候没有将timer销毁,也会导致dealloc方法不走。

if(self.timer && [self.timer isValid]) {

        [self.timer invalidate];

       self.timer =nil;

}

上面的代码最好在viewWillDisappear或者viewDidDisappear里调用,不宜在dealloc里面调用,下面引申一下在dealloc方法中应该做哪些操作!!!

=====================这是一条迷人的分割线======================

在dealloc方法中只释放引用并解除监听

对象在经历其生命期后,最终会为系统所回收,这是就要执行dealloc方法了。在每个对象的生命期内,此方法仅执行一次,也就是当保留计数降为0的时候。然而具体何时执行,则无法保证。也可以理解成:我们能够通过人工观察保留操作与释放操作的位置,来预估此方法何时执行。但实际上,程序库会以开发者察觉不到的方式操作对象,从而使回收对象的真正时机和预期的不同。我们决不应该自己调用dealloc方法。运行期系统会在适当的时候调用它。而且,一旦调用过dealloc后,对象就不再有效了,后续方法调用均是无效的。

在dealloc方法中做些什么呢?主要就是释放对象所拥有的引用,也就是把所有Objective-C对象都释放掉,ARC会通过自动生成的.cxx_destruct方法,在dealloc中为你自动添加这些释放代码。还有一件事,那就是把原来配置过的观测行为都清理掉。如果用NSNotificationCenter给此对象订阅过某种通知,那么一般应该在这里注销,这样的话,通知系统就不再把通知发给回收后的对象了,若是还向其发送,则必然会令应用程序奔溃。

注意在dealloc方法里,不要做其他事情!不要做其他事情!不要做其他事情!

结语:觉得有用的同学可以点个赞哦,一起学习,一起成长!

你可能感兴趣的:(快速定位没有调用dealloc的问题)