一:爲何形成了循環引用??????????????????????????html
首先 安全
對於網絡工具類 finishedBlock裏面 的一個屬性是 copy的網絡
那麼 NetworkTools 會對網絡工具 finishedBlock進行一個強引用異步
左邊的控制器viewController裏面 工具
viewController 對 NetworkTools對象 tools進行強引用 spa
在右邊有一個 self.finishedBlock = finished 的賦值3d
在左邊的self.view 而後呢 self.finishedBlock = finished 這個對self.view指針
進行一個強引用 htm
形成了一個閉環 finishedBlock(引用)----self.view()--(self就是那個控制器器 對NetworkTools對象 tools強引用)----tools(引用了)finshedBlock對象
產生了一個閉環 形成了一個封閉的強引用
--------結果是誰釋放不了
二:如何去打斷循環引用?????????????????????????
方式1:--打斷引用鏈條 方式2:--使用__weak
方式1: 能夠在左邊的控制器viewcontroller裏面去作一個動做
把那個 self.tools改爲一個
NetworkTools * tools 讓tools成爲一個局部的變量 懂?????
他天然在走出了做用域就會自動釋放了 打破了上面的環節 沒有了self.view
那個控制器的對他的強引用
這個就是破壞引用鏈條的原理
方式2: 在
在左邊添加了
// 方式2
__weak typeof(self) weakSelf = self;
[self.tools lodaData:^(NSString *html) {
NSLog(@"%@ %@",html,weakSelf.view);
}];
添加了這樣的東西的話 咱們就能夠的接觸循環引用的
這個引用鏈條也會被破壞掉 破壞是在那個 finishedBlock 對self.view的那個環節
整體思路的是:打破循環引用環節的任何一環就行
方法3: 使用__unsafe_unretained typeof(self) weakSelf = self;
//方法3
__unsafe_unretained typeof(self) weakSelf= self;
[self.tools lodaData:^(NSString *html) {
NSLog(@"%@ %@",html,weakSelf.view);
}];
三:對__unsafe_unretained和 __weak的深度挖掘??????????????
咱們在網絡工具類裏面去的作一個耗時操做去模仿網絡請求延時操做
__weak是iOS5.0的
這個時候 weakSelf.view打印的是null
若是異步操做沒有完成的話,他就會釋放控制器 __weak自己是弱引用
當異步操做執行完畢了的話 ,此時進行回到的時候 self已經被釋放了 沒法再去訪問屬性 也沒法調用方法 因此打印的是null
( 因此在點擊返回的快慢不一樣 打印結果不一樣)
用__unsafe_unretained的時候 __unsafe_unretained是iOS4.0推出的
程序就崩潰了 這個MRC的錯誤 壞內存訪問 野指針錯誤
__weak至關於 weak 不會作強引用 可是若是對象被釋放,執行地址會指向nil
MRC下面屬性的持有都是assign 不會作強引用 可是若是對象被釋放
內存地址還不變 此時再去調用 就會出現野指針的訪問
因此在開發中通常去推薦__weak __unsafe_unretained相對於不安全
還有一種流傳出來的代碼
(stringSelf強引用 對weakSelf進行強引用 本意 但願在執行完代碼了後 繼續執行回調)
可是若是的話__unsafe_unretained 換成這個 他仍是會崩潰的
整體的區別:
__weak 寫法的話 self 已經被釋放 只爲nil
__unsafe_unretained的話 self已經被釋放的話 就會出現野指針訪問
內部可使用 strongSelf 可是沒有深惡麼卵用