ios開發中,開了ARC模式,系統自動管理內存,如果程序中用到了block就要注意循環引用帶來的內存洩露問題了
這幾天遇到一個問題,正常頁面dismiss的時候是要調用dealloc方法的,但是我的程序就是不調用,研究了好久終於找到了問題出在哪裡了
起初的代碼如下:
- (void)getMyrelatedShops
{
[self.loadTimer invalidate];
self.loadTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:discoverView
selector:@selector(loadWaiting)
userInfo:nil
repeats:YES];
sendedRequest = [[FindShopService sharedInstance] getMyRelatedShopsWithPageNO:pageNo
successBlock:^(TMRequest *request){
[self.loadTimer invalidate];
[self shopListRequestFinished:request];
}failedBlock:^(TMRequest *failedRequest){
[self.loadTimer invalidate];
[self shopListRequestFailed:failedRequest];
}];
}
代碼表面上看起來沒有什麼問題,但是細細研究就會發現兩個問題
1、block中引用到self,self 被block retain,sendedRequest又retain了該block的一根拷貝
2.sendedRequest是在self類中定義賦值,因此是被self retain
因此就形成了循環引用,不會調用dealloc
還有一個問題,只要重復性 timer 還沒有被 invalidated,target 對象就會被一直持有而不會被釋放。因此當你使用 self 當作 target 時,你就不能期望在 dealloc 中 invalidate timer,因為在 timer 沒有被invalidate 之前,dealloc 絕不會被調用。因此,需要找個合適的時機和地方來 invalidate timer,但絕不是在 dealloc 中。
修改如下
- (void)getMyrelatedShops
{
[self.loadTimer invalidate];
self.loadTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:discoverView
selector:@selector(loadWaiting)
userInfo:nil
repeats:YES];
__unsafe_unretained FindShopVC *wfindShopVC = self;
sendedRequest = [[FindShopService sharedInstance] getMyRelatedShopsWithPageNO:pageNo
successBlock:^(TMRequest *request){
[wfindShopVC.loadTimer invalidate];
[wfindShopVC shopListRequestFinished:request];
}failedBlock:^(TMRequest *failedRequest){
[wfindShopVC.loadTimer invalidate];
[wfindShopVC shopListRequestFailed:failedRequest];
}];
}
這樣就避免了循環引用,頁面注銷時就會調用dealloc方法了