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