講述Sagit.Framework解決:雙向引用導致的IOS記憶體流失(上),sagit.frameworkios

來源:互聯網
上載者:User

講述Sagit.Framework解決:雙向引用導致的IOS記憶體流失(上),sagit.frameworkios
前言:

好久沒寫文章了,最近先是重構IT戀、又重寫IT戀中。

Sagit架構也不斷的更新,調整,現在感覺已完美了了相當的多。

今天不寫教程,先簡單分享一下技術內容。

1:見Block必有:#define WeakSelf __weak typeof(self) this = self;

 故事要從這這裡說起:

當初番完這代碼後,發現到處都有這個鬼東西,然後就去百度了一下,然後大意是為了:

解決雙向引用導致的記憶體無法釋放問題

簡單的表述如下:

self   強引用指向=》block;block 也強引用批向=>self;

這時候就出事了,解決的方法是,把其中一個改成弱指向。

而WeakSelf的定義,就是讓block改成弱引用,這樣無論self是不是強引用的指向block都無關緊要了。當然,更精緻的做法是:先預判self有沒有強引用指向block,沒有,就不用WeakSelf定義了。不過,一般新手搞不明白內涵,無法做出有效預判,所以見block就有WeakSelf也就相隨相生了。
2:其它情境的雙向引用:UIViewController與UIView的糾纏

 首先,預設UIViewController有一個強引用指向了UIView,這是系統定義的,我們改不了:

所以,如果UIView裡再出現strong或retain指回UIController,就會導致UIViewController和UIView雙雙無法釋放問題。

這個問題,在我剛寫Sagit架構時,只在意功能,沒在意這些,就犯了這個錯誤:

錯誤的寫法是這樣的:

現在改正後的寫法是這樣的:

3:事情沒有這麼簡單:UIView子控制項綁定事件指向Controller

看一行Sagit的代碼,關注後面的addClick:

[[[[sagit addButton:@"Login" title:@"登入" font:40] width:450 height:80] onBottom:@"pwdLine" y:149] addClick:@"loginClick"];

對於事件流程關於Sagit的前面幾篇有說了,這裡說一下架構的流程代碼:

1:系統自動添加了一個UITapGestureRecognizer,並指定到一個固定的click方法;2:將方法名稱和target存到自身的NSDictionary的字典中(架構為每個UIView都擴充了一個Dictionary)(就是這裡造成強引用了Controller).3:事件點擊時:先觸發系統預設的click,然後click事件:從字典裡取出方法名和target,找到SEL並動態執行。PS:設計成動態執行的好處:可以在執行前處理一些其它事情:比如將addClick參數:loginClick改成AgeButton.click,這樣可以分解參數後,去執行AgeButton上的事件

執行的代碼是這樣的,由於是動態執行,少不了還有一個警告:

接下來,就是怎麼消滅事件裡對Controller的強引用:
1:找了資料,發現有個NSMapTable,是弱引用的字典,於是把NSDictionary換成它,結果:參不忍睹,介面錯亂。【大概是弱引用特別容易遺失資料】 
2:嘗試用一個全域的第三方的字典來存,結果也悲哀了!3:最後想到了一個方法,不直接存Controller,只存字串:1和0 ,在最終執行的時候,再去找。

代碼是這樣的:

真難為我這麼聰明,想著大功告成,運行,釋放了,成功了!!!

然後又悲哀了:

然後就動不動就到main含數了,讓我怎麼猜?說好的全域斷點呢?你咋不斷呢?

搜了搜百度,想想要調度記憶體,那就一個蛋騰,還是靠猜吧。

後來,根據釋放的順序,和最後的關鍵字,大概是這樣猜的:

控制器被釋放了,這時候UIView還沒釋放,然後系統又給UIView綁字的事件發訊息,結果遇到野指標,悲傷的故事發生了。

於是,我做了一個艱難的決定,在UIController的deallow中寫了這樣的代碼:

-(void)dealloc{    [self.view removeAllsubViews];//處理記憶體釋放後的異常。    NSLog(@"%@ ->UIViewControlelr relase", [self class]);}

這執行dealloc前,畢竟Controller還是活著的,這時候趕緊把UIView的東西給清了,然後,發現完美,運行起來很6!

總結:

當我很6的解決完上述問題後,就開始寫文章了想分享一下了,然後寫了開頭,發現:

咦,好像UITableView和UITableViewCell,好像也有雙向引用問題。

因為我給Cell加了個屬性,指向Table,運行,果然,Shit,連Controller和父的UIView都釋放了,你UITableView做為子UI居然不釋放!!!!

沒天理,繼續折騰,然後UITableView搞釋放了,又發現UITableViewCell不釋放了(這個Cell通常又會是一大堆UI)。

再然後,發現Push兩層回來,又掛Crash了。

現在正在全力搶救!!!解決完再來寫下篇!!!

 

操,發現為了釋放那點記憶體的代價,折騰起來真慘過不釋放算了〜〜〜〜

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.