讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上)
前言:
好久沒寫文章了,最近先是重構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了。
現在正在全力搶救!!!解決完再來寫下篇!!!
?
操,發現為了釋放那點內存的代價,折騰起來真慘過不釋放算了????
轉載于:https://www.cnblogs.com/cyq1162/p/8195220.html
總結
以上是生活随笔為你收集整理的讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样才能正确地烹饪食物?
- 下一篇: 日利率和月利率