block-循環引用
在ARC機制下,app的內存管理由操作系統進行管理,不須要程序猿手動的管理內存,方便了開發.雖然,自己主動釋放內存非常方便。可是並不是絕對安全,絕對不會產生內存泄露。
大部分導致iOS對象無法按預期釋放的一個無形殺手是——循環引用。
循環引用能夠簡單理解為A引用了B,而B又引用了A,兩方都同一時候保持對方的一個強引用。導致不論什麽時候引用計數都不為0,始終無法釋放。
以下我們介紹下block代碼塊,引起的循環引用以及解決的方法
block在copy時都會對block內部用到的對象進行強引用。第一種easy引起循環引用的一般表現為。某個類將block作為自己的屬性變量,然後該類在block的方法體裏面又使用了該類本身。簡單說就是self.MyBlock = ^(Type var){[self dosomething]; 或者self.otherVar = XXX;或者_otherVar = …}, 造成了self 擁有一個block的時候,在block 又調用self的方法。block的這樣的循環引用會被編譯器捕捉到並及時提醒。
舉比例如以下(People類):
我們能夠看出在block的實現內部又使用了People類(self)的name屬性。這個時候,編譯器提醒給出了相關的警告.
解決方法:
通過使用_weak聲明一個取代self的新變量取代原先的self,命名為weakSelf。通過這樣的方式告訴block,不要在block內部對self進行強制強引用.
這樣的循環引用的事例圖為:
另外一種情況為:比如self 有一個button ,而你有要 調用 button的某個東西設置.[self.button ^{ }]因為某些原因,你又要在這個block裏調用self的其它控件,比如self.textField.text = @”text”;就造成了訊混引用。
(即:控制器中有一個控件,在這個控件中又訪問了控制器的其它控件).比如AlertController中的Action對象訪問AlertController的textField對象.
為了進行演示的事例:首先我們定義了一個UIAlertController的子類(AlertController),並實現它的dealloc方法
- (void)dealloc{
NSLog(@"alertController dealloc");
}
在主控制器中創建AlertController,並實現點擊確認的方法(獲取其上的文本框內容信息)
點擊確認後,打印例如以下
我們發如今銷毀AlertController的時候,AlertController並沒有釋放,導致了內存的泄露.
改動為例如以下方式,點擊確認後結果為:
能夠看出,對象得到釋放.
沒有改動之前的事例圖為:
解決循環引用後
解決方法
簡而言之就一句話的事情:
__weak typeof (self) weakSelf = self;
block-循環引用