MLeaksFinder原理&AOP

MLeaksFinder原理:MLeaksFinder 一開始從 UIViewController 入手萌丈。我們知道昵时,當(dāng)一個 UIViewController 被 pop

或 dismiss 后顺献,該 UIViewController 包括它的 view,view 的 subviews

等等將很快被釋放(除非你把它設(shè)計成單例厌衙,或者持有它的強引用畦木,但一般很少這樣做)。于是申窘,我們只需在一個 ViewController 被 pop 或

dismiss 一小段時間后弯蚜,看看該 UIViewController,它的 view剃法,view 的 subviews 等等是否還存在碎捺。

具體的方法是,為基類 NSObject 添加一個方法-willDealloc方法,該方法的作用是收厨,先用一個弱指針指向 self晋柱,并在一小段時間(3秒)后,通過這個弱指針調(diào)用-assertNotDealloc诵叁,而-assertNotDealloc主要作用是直接中斷言雁竞。

- (BOOL)willDealloc {

__weakidweakSelf =self;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

? ? ? ? [weakSelf assertNotDealloc];

? ? });

returnYES;

}

- (void)assertNotDealloc {

NSAssert(NO, @“”);

}

這樣,當(dāng)我們認(rèn)為某個對象應(yīng)該要被釋放了拧额,在釋放前調(diào)用這個方法碑诉,如果3秒后它被釋放成功,weakSelf 就指向 nil侥锦,不會調(diào)用到-assertNotDealloc方法联贩,也就不會中斷言,如果它沒被釋放(泄露了)捎拯,-assertNotDealloc就會被調(diào)用中斷言泪幌。這樣,當(dāng)一個 UIViewController 被 pop 或 dismiss 時(我們認(rèn)為它應(yīng)該要被釋放了)署照,我們遍歷該 UIViewController 上的所有 view祸泪,依次調(diào)-willDealloc,若3秒后沒被釋放建芙,就會中斷言没隘。

在這里,有幾個問題需要解決:

1.不入侵開發(fā)代碼

這里使用了 AOP 技術(shù)禁荸,hook 掉 UIViewController 和 UINavigationController 的 pop 跟 dismiss 方法右蒲,關(guān)于如何 hook,請參考Method Swizzling赶熟。

2.遍歷相關(guān)對象

在實際項目中瑰妄,我們發(fā)現(xiàn)有時候一個 UIViewController 被釋放了,但它的 view 沒被釋放映砖,或者一個 UIView

被釋放了间坐,但它的某個 subview 沒被釋放。這種內(nèi)存泄露的情況很常見邑退,因此竹宋,我們有必要遍歷基于 UIViewController 的整棵

View-ViewController 樹。我們通過 UIViewController 的 presentedViewController 和

view 屬性地技,UIView 的 subviews 屬性等遞歸遍歷蜈七。對于某些 ViewController,如

UINavigationController莫矗,UISplitViewController 等飒硅,我們還需要遍歷 viewControllers

屬性砂缩。

3.構(gòu)建堆棧信息

需要構(gòu)建 View-ViewController stack 信息以告訴開發(fā)者是哪個對象沒被釋放。在遞歸遍歷 View-ViewController 樹時狡相,子節(jié)點的 stack 信息由父節(jié)點的 stack 信息加上子結(jié)點信息即可梯轻。

4.例外機(jī)制

對于有些 ViewController食磕,在被 pop 或 dismiss 后尽棕,不會被釋放(比如單例),因此需要提供機(jī)制讓開發(fā)者指定哪個對象不會被釋放彬伦,這里可以通過重載上面的-willDealloc方法滔悉,直接 return NO 即可。

5.特殊情況

對于某些特殊情況单绑,釋放的時機(jī)不大一樣(比如系統(tǒng)手勢返回時回官,在劃到一半時 hold 住,雖然已被 pop搂橙,但這時還不會被釋放歉提,ViewController 要等到完全 disappear 后才釋放),需要做特殊處理区转,具體的特殊處理視具體情況而定苔巨。

6.系統(tǒng)View

某些系統(tǒng)的私有 View,不會被釋放(可能是系統(tǒng) bug 或者是系統(tǒng)出于某些原因故意這樣做的废离,這里就不去深究了)侄泽,因此需要建立白名單

7.手動擴(kuò)展

MLeaksFinder目前只檢測 ViewController 跟 View 對象。為此蜻韭,MLeaksFinder

提供了一個手動擴(kuò)展的機(jī)制悼尾,你可以從 UIViewController 跟 UIView

出發(fā),去檢測其它類型的對象的內(nèi)存泄露肖方。如下所示闺魏,我們可以檢測 UIViewController 底下的 View Model:

- (BOOL)willDealloc {

if(![superwillDealloc]) {

returnNO;

? ? }

MLCheck(self.viewModel);

returnYES;

}

這里的原理跟上面的是一樣的,宏 MLCheck() 做的事就是為傳進(jìn)來的對象建立 View-ViewController stack 信息俯画,并對傳進(jìn)來的對象調(diào)用-willDealloc方法舷胜。

、活翩、烹骨、、材泄、沮焕、、拉宗、峦树、辣辫、、魁巩、急灭、、谷遂、葬馋、、肾扰、畴嘶、、集晚、窗悯、、偷拔、蒋院、、莲绰、欺旧、、钉蒲、切端、、顷啼、踏枣、、钙蒙、茵瀑、、躬厌、马昨、、扛施、鸿捧、

AOP:在運行時,動態(tài)地將代碼切入到類的指定方法疙渣、指定位置上的編程思想就是面向切面的編程.向切面編程(AOP是Aspect Oriented Program的首字母縮寫) 匙奴,我們知道,面向?qū)ο蟮奶攸c是繼承妄荔、多態(tài)和封裝泼菌。而封裝就要求將功能分散到不同的對象中去谍肤,這在軟件設(shè)計中往往稱為職責(zé)分配。實際上也就是說哗伯,讓不同的類設(shè)計不同的方法荒揣。這樣代碼就分散到一個個的類中去了。這樣做的好處是降低了代碼的復(fù)雜程度焊刹,使類可重用系任。

但是人們也發(fā)現(xiàn),在分散代碼的同時伴澄,也增加了代碼的重復(fù)性赋除。什么意思呢阱缓?比如說非凌,我們在兩個類中,可能都需要在每個方法中做日志荆针。按面向?qū)ο蟮脑O(shè)計方法敞嗡,我們就必須在兩個類的方法中都加入日志的內(nèi)容。也許他們是完全相同的航背,但就是因為面向?qū)ο蟮脑O(shè)計讓類與類之間無法聯(lián)系喉悴,而不能將這些重復(fù)的代碼統(tǒng)一起來。

也許有人會說玖媚,那好辦啊箕肃,我們可以將這段代碼寫在一個獨立的類獨立的方法里,然后再在這兩個類中調(diào)用今魔。但是勺像,這樣一來,這兩個類跟我們上面提到的獨立的類就有耦合了错森,它的改變會影響這兩個類吟宦。那么,有沒有什么辦法涩维,能讓我們在需要的時候殃姓,隨意地加入代碼呢?這種在運行時瓦阐,動態(tài)地將代碼切入到類的指定方法蜗侈、指定位置上的編程思想就是面向切面的編程。

一般而言睡蟋,我們管切入到指定類指定方法的代碼片段稱為切面踏幻,而切入到哪些類、哪些方法則叫切入點薄湿。有了AOP叫倍,我們就可以把幾個類共有的代碼偷卧,抽取到一個切片中,等到需要時再切入對象中去吆倦,從而改變其原有的行為听诸。

這樣看來,AOP其實只是OOP的補充而已蚕泽。OOP從橫向上區(qū)分出一個個的類來晌梨,而AOP則從縱向上向?qū)ο笾屑尤胩囟ǖ拇a。有了AOP须妻,OOP變得立體了仔蝌。如果加上時間維度,AOP使OOP由原來的二維變?yōu)槿S了荒吏,由平面變成立體了敛惊。從技術(shù)上來說,AOP基本上是通過代理機(jī)制實現(xiàn)的绰更。

AOP在編程歷史上可以說是里程碑式的瞧挤,對OOP編程是一種十分有益的補充。

鏈接:https://www.zhihu.com/question/24863332/answer/48376158

MLeaksFinder:http://wereadteam.github.io/2016/02/22/MLeaksFinder/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末儡湾,一起剝皮案震驚了整個濱河市特恬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌徐钠,老刑警劉巖癌刽,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尝丐,居然都是意外死亡显拜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門摊崭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讼油,“玉大人,你說我怎么就攤上這事呢簸“ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵根时,是天一觀的道長瘦赫。 經(jīng)常有香客問我,道長蛤迎,這世上最難降的妖魔是什么确虱? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮替裆,結(jié)果婚禮上校辩,老公的妹妹穿的比我還像新娘窘问。我一直安慰自己,他們只是感情好宜咒,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布惠赫。 她就那樣靜靜地躺著,像睡著了一般故黑。 火紅的嫁衣襯著肌膚如雪儿咱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天场晶,我揣著相機(jī)與錄音混埠,去河邊找鬼。 笑死诗轻,一個胖子當(dāng)著我的面吹牛钳宪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播概耻,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼使套,長吁一口氣:“原來是場噩夢啊……” “哼罐呼!你這毒婦竟也來了鞠柄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤嫉柴,失蹤者是張志新(化名)和其女友劉穎厌杜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體计螺,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡夯尽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了登馒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匙握。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖陈轿,靈堂內(nèi)的尸體忽然破棺而出圈纺,到底是詐尸還是另有隱情,我是刑警寧澤麦射,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布蛾娶,位于F島的核電站,受9級特大地震影響潜秋,放射性物質(zhì)發(fā)生泄漏蛔琅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一峻呛、第九天 我趴在偏房一處隱蔽的房頂上張望罗售。 院中可真熱鬧辜窑,春花似錦、人聲如沸寨躁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朽缎。三九已至惨远,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間话肖,已是汗流浹背北秽。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留最筒,地道東北人贺氓。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像床蜘,于是被迫代替她去往敵國和親辙培。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容