上次處理了一個因為控制器被某種強(qiáng)引用而無法釋放掉,系統(tǒng)沒用幫我們釋放掉此對象的這塊內(nèi)存的問題,控制器在pop出棧的時候也沒有調(diào)用到dealloc方法,當(dāng)時一時間沒有定位出這個強(qiáng)引用的類型以及具體位置,趕開發(fā)進(jìn)度的需要對控制器做了一個特殊處理,也算是解決了當(dāng)時的需求(調(diào)用pop方式返回,但是當(dāng)前控制器沒有被釋放的解決方式),但是強(qiáng)引用沒定位出來卻在心里留下了一根刺...今天專門抽出時間來定位這個問題.
控制器沒有被釋放大致原因有幾點(diǎn):
1.viewController中NSTimer沒有被銷毀
2.viewController中的代理不是weak屬性
3.viewController中block的循環(huán)引用
1,2很簡單被排除掉了,剩下的還是block的循環(huán)引用問題,這個需要一點(diǎn)點(diǎn)的定位:
NSLogDealloc
是一個宏定義:#define NSLogDealloc NSLog( @"<< %@ : dealloc done >>", [[NSString stringWithUTF8String:__FILE__] lastPathComponent])
,只要正常釋放了我們都能在控制臺打印出<< XXConfirmOrderController.m : dealloc done >>
這個類里的結(jié)構(gòu)很簡單, 視圖及數(shù)據(jù)的處理都是在
-(void)viewDidLoad{ }
方法內(nèi)處理,由圖片我們看出,我們只需要分別追從排除
//UI
[self.view addSubview:self.tableView];
[self.view addSubview:self.bottomView];
//Data
[self loadData];
以及3各通知就好.
通過注釋排除的方式將
[self.view addSubview:self.tableView]; [self loadData];
很容易的排除掉了,只有當(dāng)[self.view addSubview:self.bottomView];
打開的時候,控制器沒有被正常釋放掉.ok,問題出在這里. 定位到self.bottomView
,跳入其懶加載查看了好幾遍,終于找到了問題:
后面代碼較長也沒問題就不貼了.看這里代碼好像都已經(jīng)做好了循環(huán)引用的處理了,block內(nèi)所有用到self的地方都做了弱引用處理,但是還是執(zhí)行不到dealloc方法,一點(diǎn)點(diǎn)追蹤問題,最后將WEAKHUD 提到block之外時,就能執(zhí)行到dealloc方法:
于是點(diǎn)進(jìn)去WEAKHUD一看究竟,最后發(fā)現(xiàn)這個宏定義坑爹的寫了:
#define WEAKHUD __weak MBProgressHUD *weakHud = [MBProgressHUD showMessage:@"加載中..." toView:self.view];
最后引用的是self.view, 還是TMD強(qiáng)引用!!!!!!????????????????###
OK,問題找到了.
這里歸根結(jié)底還是觸犯了block的使用規(guī)則:只有當(dāng)block直接或間接的被self持有時,就需要weak self涵妥。#####
這里在做按鈕點(diǎn)擊事件處理時,從self.bottomView
內(nèi)甩出來一個block回調(diào)
[_bottomView submittBtnPressed:^(UIButton *btn) { }];
self對bottomView是毫無疑問的強(qiáng)引用@property(nonatomic, strong) XXSubmitBottomView *bottomView;
跳入XXSubmitBottomView內(nèi),里面
@property(nonatomic, copy)BtnPressedBlock block; -(void)submittBtnPressed:(BtnPressedBlock)block;
毫無疑問的bottomView對block也是強(qiáng)引用,因此self.bottomView.block
間,self間接持有了block,就產(chǎn)生了間接的循環(huán)引用!!!
只要問題找到了,解決問題就很簡單了:
其實我們這里壓根用不到去弱引用WEAKHUD
hud放在block內(nèi)執(zhí)行時正確的,放在外面反而錯誤,那樣在按鈕點(diǎn)擊之前就會有hud一直在轉(zhuǎn)...
MBProgressHUD是在此處生成了一個對象hud,hud并沒有被self所持有,hud和block之間也沒有互相引用,所以只需要簡單去創(chuàng)建一個hud就好了
要注意給hud加顯示層時,千萬要將
self.view
替換成weakSelf.view
,這樣就解決了循環(huán)引用的問題.
dealloc終于被執(zhí)行到.
這個刺終于拔出來了...