背景:
近期在做公司內(nèi)部使用的iOS應(yīng)用性能檢測(cè)組件及項(xiàng)目性能優(yōu)化的工作,有個(gè)需求是能量化的統(tǒng)計(jì)各個(gè)界面的啟動(dòng)耗時(shí)。
通常,項(xiàng)目中頁(yè)面啟動(dòng)的耗時(shí)長(zhǎng)短通常肉眼可見(jiàn),但當(dāng)我們?cè)趯?duì)項(xiàng)目進(jìn)行界面啟動(dòng)耗時(shí)優(yōu)化時(shí),我們通常需要知道VC啟動(dòng)耗時(shí)的數(shù)據(jù),并收集進(jìn)行對(duì)比,此時(shí)我們需要能夠?qū)崿F(xiàn)記錄界面啟動(dòng)耗時(shí)的數(shù)據(jù)來(lái)進(jìn)行量化的分析。
方案分析:

通常這種通用的需求,我們首先想到的方案便是使用AOP,針對(duì)VC的生命周期方法進(jìn)行swizzle,打點(diǎn)記錄每個(gè)生命周期方法的時(shí)間點(diǎn),即可獲取VC的耗時(shí)。但是實(shí)際實(shí)踐這種方案存在一個(gè)弊端,因?yàn)槲覀僪ook 的是UIViewController的方法,果我們?cè)谧约旱?VC 中重寫了對(duì)應(yīng)的方法,并執(zhí)行了一些耗時(shí)的操作,那么這些操作的時(shí)間就沒(méi)有被計(jì)算進(jìn)去。所以,基于這個(gè)方案,需要做進(jìn)一步的改進(jìn)。
目前使用的改進(jìn)方案是:
1.對(duì)需要監(jiān)聽(tīng)的類的實(shí)例化時(shí)進(jìn)行KVO,監(jiān)聽(tīng)一個(gè)不存在的KeyPath。通過(guò)它來(lái)創(chuàng)建子類。
2.對(duì)KVO創(chuàng)建出來(lái)的子類添加需要Swizzle的方法對(duì)應(yīng)的SEL及其IMP。因?yàn)楸举|(zhì)上KVO只是對(duì)setter和getter方法進(jìn)行了override,如果不提供自定義的實(shí)現(xiàn),還是會(huì)調(diào)用到原來(lái)的類的IMP。
3.在實(shí)例銷毀的時(shí)候,將KVO監(jiān)聽(tīng)移除,避免導(dǎo)致KVO still registering when deallocated這樣的Crash。
4.對(duì)于記錄的界面耗時(shí)記錄信息,收集到一份列表中,有一個(gè)recorder類維護(hù)列表,并提供一個(gè)List界面進(jìn)行展示,可以在程序中直接查看檢測(cè)數(shù)據(jù)。
具體實(shí)現(xiàn)可見(jiàn)我的Github
參考: