非主線程刷UI
hook UIView的下列三個(gè)方法:
- setNeedsLayout
- setNeedsDisplay
- setNeedsDisplayInRect
判斷當(dāng)前是否在主線程,如果不在則通過(guò)dispatch_async(dispatch_get_main_queue(), ^{ //調(diào)用原本方法 });瓢省,此方法暫時(shí)不能做到完全覆蓋
訪問(wèn)野指針
- hook NSObject 的allocWithZone方法,判斷當(dāng)前對(duì)象是否需要加入野指針?lè)雷o(hù)。因?yàn)楹芏嘞到y(tǒng)類(lèi)釋放頻繁,且發(fā)生野指針的概率較低,過(guò)濾可以提高效率
- hook NSObject 的dealloc方法厕倍,根據(jù)過(guò)濾方式,調(diào)用objc_destructInstance贩疙,釋放該實(shí)例引用的相關(guān)屬性讹弯,然后調(diào)用object_setClass()方法,將實(shí)例的isa修改為自定義的一個(gè)處理對(duì)象
NSArray这溅、NSDictionary组民、NSString防護(hù)
hook真實(shí)的類(lèi)型的對(duì)應(yīng)方法即可,注意要hook真實(shí)類(lèi)型
Unrecognized Selector
根據(jù)消息轉(zhuǎn)發(fā)流程悲靴,選擇在哪一個(gè)階段攔截
- resolveInstanceMethod 需要給類(lèi)動(dòng)態(tài)添加方法臭胜,會(huì)增加沒(méi)必要的開(kāi)銷(xiāo)
- forwardInvocation 可以動(dòng)態(tài)轉(zhuǎn)發(fā)給多個(gè)對(duì)象,開(kāi)銷(xiāo)較大
- forwardingTargetForSelector轉(zhuǎn)發(fā)給單個(gè)對(duì)象處理癞尚,比較合適
KVO
奔潰發(fā)生在以下情況
- 被觀察者dealloc時(shí)仍然注冊(cè)著KVO導(dǎo)致的crash
- 重復(fù)添加觀察者或重復(fù)移除觀察者
解決方案耸三,hook NSObject的addObserver和removeObserver方法,并且給NSObject添加一個(gè)關(guān)聯(lián)對(duì)象浇揩,用來(lái)存儲(chǔ)觀察者和被觀察者關(guān)系仪壮,并將觀察者轉(zhuǎn)移給關(guān)聯(lián)對(duì)象,關(guān)聯(lián)對(duì)象內(nèi)部判斷對(duì)應(yīng)的keyPath是否已經(jīng)添加了對(duì)應(yīng)的觀察者胳徽,或者移除了對(duì)應(yīng)的觀察者积锅。關(guān)聯(lián)對(duì)象內(nèi)部hook observeValueForKeyPath方法爽彤,將實(shí)踐回調(diào)轉(zhuǎn)給原來(lái)的觀察者。NSObject 還需要hook dealloc方法乏沸,用于在被觀察者釋放的時(shí)候淫茵,注銷(xiāo)觀察關(guān)系
NSNotification
在對(duì)象釋放的時(shí)候,如果沒(méi)有移除通知蹬跃,在iOS9之前會(huì)存在奔潰問(wèn)題匙瘪。
解決方案,hook NSObject 的dealloc方法蝶缀,添加[[NSNotificationCenter defaultCenter] removeObserver:self]方法即可