iOS中常见的造成dealloc不调用的原因

iOS开发中常见的造成dealloc不调用的原因

自己遇到的问题描述:
最近项目里要用到AVPlayer播放器,自己便写了一个简单的播放器,但是却遇到了一个很奇怪的问题,,在播放中途点击了关闭按钮,dismiss了VideoPlayerViewController,但是画面关闭了,声音一直还在,而且内存爆增。 后来几经发现才找到问题所在,是VideoPlayerViewController在dismiss的时候并没有被释放,从而导致引用的VideoPlayView没有走dealloc方法,进而导致AVPlayerItem调用了KVO回调方法之后没有被移除监听([self.currentItem removeObserver:self forKeyPath:@”status” context:nil];放在了dealloc方法里)。。从而开始寻找dealloc没有被释放的原因。

总结方法:
1.ViewController中存在NSTimer
如果你的ViewController中有NSTimer,那么当你调用了

NSTimer scheduledTimerWithTimeInterval:1.0 
                                 target:self 
                               selector:@selector(updateTime:) 
                               userInfo:nil 
                                repeats:YES];

这个target:self 就增加了ViewController的return count,如果你不使用[timer invalidate] 销毁计时器,那就不会走dealloc方法。

2.ViewController中有Block
Block体内使用实例变量也会造成循环引用,使得拥有这个实例的对象不能释放。 例如你这个类叫ViewController,有个属性是NSString *name; 如果你在block体中使用了self.name,那样子的话这个类就没法释放。
要解决这个问题只需

__weak typeof(self) weakself = self;

3.ViewController中有关的代理
这个就是我上面不走dealloc的真正原因,,,一个比较隐秘的因素,你去找找与这个类有关的代理,看有没有强引用属性?比如一个代理的delegate应该是 assign 的现在是retain,就是这个,它会影响你不让你调用dealloc。 我这里是因为VideoPlayerViewController里在建立URLSession会话的时候,使用了NSURLSession的代理,,这个代理是强引用的,session会话如果不主动取消,就会造成循环引用,导致内存泄漏。
这里的解决办法:

@interface VideoPlayerViewController () <NSURLSessionDelegate>
@property (nonatomic, strong) NSURLSession *session; 
@end
//懒加载自定义文件下载的session,并设置代理
- (NSURLSession *)session{
    if (_session == nil) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];  //这个代理是强引用的
    }
    return _session;
}
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    //在viewDidDisappear方法里手动关闭会话
    [self.session invalidateAndCancel];
}

这样就解决了一开始描述的那个问题了,,但是有一点要注意的是,session一旦被取消就无法再次使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章