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一旦被取消就無法再次使用。

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