正確使用Block避免循環(huán)引用

很多剛?cè)腴T的寶寶面對block是心虛的,因為一提到block就會聯(lián)想到:如果用的不好會出現(xiàn)循環(huán)引用引起內(nèi)存泄漏問題,有時候想用但是自己又沒有能發(fā)現(xiàn)循環(huán)引用的洞察力,所以在遇到block存在的地方,就使用__weak type(self) weakSelf = self;(被視為解決循環(huán)引用的必備良藥) 這句話加上確實能保證不會出現(xiàn)循環(huán)引用的情況,但是并不是所有使用block的地方都會出現(xiàn)循環(huán)引用的,所以這個要具體問題具體對待,該用時那必須得用,沒必要的時候,也就沒有必要畫蛇添足了。
下面列舉一處常見使用Block的例子,但是一般不會輕易出現(xiàn)循環(huán)引用,只要把關(guān)鍵點處理好就不會出現(xiàn)循環(huán)引用的問題。例子一:UIAlertController(彈出框視圖控制器)想必大家再也熟悉不過了

//點擊按鈕彈出提示框
-(void)btnAction:(id)sender{ 
  NSLog(@"彈出框"); 
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"彈出框" message:@"" preferredStyle:UIAlertControllerStyleAlert]; 
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"確定" 
                                   style:UIAlertActionStyleDefault 
                                   handler:^(UIAlertAction * _Nonnull action) { 
                                    NSLog(@"Class****%@",[self class]); 
//明目張膽在block中引用self,很多懼怕block中引用self會出現(xiàn)循環(huán)引用的寶寶會來這么一句:
      __weak type(self) weakSelf = self; 
//接著NSLog(@"Class****%@",[weakSelf class]);然后心里才放心!其實這些都是畫蛇添足,完全沒有必要的! 
}];
      UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 
      [alert addAction: ok];
      [alert addAction:cancel];
      [self presentViewController:alert animated:YES completion:nil];
}

這里把引用關(guān)系列一下就明白為什么安全無事了:


引用關(guān)系圖.png

這里根本都沒有造成閉環(huán)構(gòu)成循環(huán)引用,前提是:你沒有把UIAlertController對象或者UIAlertAction對象作為當前類的成員屬性,一但self強引用了UIAlertController對象或者強引用了UIAlertAction對象,那么就構(gòu)成閉環(huán)了,循環(huán)引用就會出現(xiàn)。一般編程中,沒有必要把UIAlertController對象或者UIAlertAction對象作為當前視圖控制器類的成員屬性,去讓self去持有它們的引用,一般都是像在本例中:在方法體中作為局部臨時對象使用(self不會持有臨時對象的引用),局部臨時對象作用域只限制在方法體內(nèi)部,也就是說這些臨時對象的生命周期只限制在方法內(nèi)部,一但方法執(zhí)行完畢,這些臨時創(chuàng)建的指針變量就會被置為nil
,如果指針被置為nil
,那么它原來所指臨時對象就會被銷毀。記?。壕植恐羔樧兞?,出了作用域就會被置為nil
,所指向的對象也會立即被系統(tǒng)釋放。
想測試到底會不會出現(xiàn)循環(huán)引用的有一個很簡單的方法:就是在self.navigationController中pop掉當前控制器對象的時候(前提使用UINavigationController作為根視圖控制器),看看當前視圖控制器類中dealloc方法是否被執(zhí)行,如果成功執(zhí)行說明沒有其他對象引用當前即將要pop掉的視圖控制器,如果不執(zhí)行,那么基本可以斷定是由于代碼中出現(xiàn)了循環(huán)引用,導致內(nèi)存泄漏,無法得到釋放的緣故。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容