1. 程式人生 > >block-循環引用

block-循環引用

lin 機制 sdn 取代 ring mark ios his 文本

在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-循環引用