解決iOS中常見的幾種Crash

最近正好有空恩够,總結(jié)一下以前項(xiàng)目中遇到的幾種常見崩潰,并且在無侵入的情況下解決這些崩潰栖秕。

常見的崩潰類型

1.數(shù)組越界,nil值初始化導(dǎo)致的崩潰缓熟。

2.對(duì)字典插入nil值累魔,或者讀取NSNULL導(dǎo)致的崩潰摔笤。

3.字符串的截取越界導(dǎo)致的崩潰。

4.doesNotRecognizeSelector導(dǎo)致的崩潰垦写。

5.子線程初始化UIView導(dǎo)致的崩潰吕世。

6.KVO的重復(fù)添加、刪除梯投,或者忘了刪除導(dǎo)致的崩潰命辖。

對(duì)于以上崩潰,如果是新產(chǎn)品分蓖,或者是代碼全部是可以修改的情況下尔艇,可以通過檢查代碼的方式來解決這些問題,但是對(duì)于一些老的項(xiàng)目么鹤,或者集成了第三方庫的項(xiàng)目呢终娃,老項(xiàng)目修改動(dòng)作太大,第三方庫只能指望更新來解決了蒸甜,這都不是我們需要的方式棠耕,所以這種情況下,就需要我們的無侵入解決方案了柠新。

說到無侵入窍荧,大家首先想到的肯定是Method Swizzling,沒錯(cuò)恨憎,下面我們就利用Method Swizzling來解決以上崩潰蕊退。

先寫上大家熟悉的方法交換的代碼


+ (void)exchangeInstanceMethod:(Class)anClass originMethodSel:(SEL)originSEL replaceMethodSel:(SEL)replaceSEL{

    MethodorigIndex =class_getInstanceMethod(anClass, originSEL);

    MethodoverrideIndex =class_getInstanceMethod(anClass, replaceSEL);

    if(!origIndex || !overrideIndex) {

        return;

    }

    method_exchangeImplementations(origIndex, overrideIndex);

}

+ (void)exchangeClassMethod:(Class)anClass originMethodSel:(SEL)originSEL replaceMethodSel:(SEL)replaceSEL

{

    MethodorigIndex =class_getClassMethod(anClass, originSEL);

    MethodoverrideIndex =class_getClassMethod(anClass, replaceSEL);

    if(!origIndex || !overrideIndex) {

        return;

    }

    method_exchangeImplementations(origIndex, overrideIndex);

}

然后說一下整體的思路

1.數(shù)組越界,nil值初始化導(dǎo)致的崩潰憔恳。

這種情況要解決很容易瓤荔,網(wǎng)上很多這方面的文章,就是通過方法交換原NSArray的objectAtIndex喇嘱,然后加一層索引判斷就夠了茉贡,這里就不多做介紹了。

需要特別注意的就是NSArray初始化的時(shí)候有空值的情況者铜。

2.對(duì)字典插入nil值腔丧,或者讀取NSNULL導(dǎo)致的崩潰。

這種崩潰的解決思路和NSArray一樣作烟,單獨(dú)提出來愉粤,只是因?yàn)榻?jīng)常出現(xiàn)服務(wù)器返回的數(shù)據(jù)是null的远舅,如果在使用時(shí)不對(duì)數(shù)據(jù)類型進(jìn)行判斷的話铃辖,就會(huì)出現(xiàn)NSNULL類型與所需要的類型不一樣,導(dǎo)致崩潰 择镇。所以這是一個(gè)需要注意的地方。

3.字符串的截取越界導(dǎo)致的崩潰影暴。

崩潰處理方式與上面一樣错邦。

說到這,再提個(gè)概念類簇型宙,只有明白什么是類簇撬呢,才能知道為什么我們做方法交換的時(shí)候不直接使用[self class],我們上面要修改的幾個(gè)類NSArray妆兑,NSDictionary魂拦,NSString都是類簇,它們的Class比較多搁嗓,需要盡量多的枚舉所有可能的Class芯勘。

4.doesNotRecognizeSelector導(dǎo)致的崩潰

doesNotRecognizeSelector也是一種比較常見的崩潰,相信大家都了解iOS的消息轉(zhuǎn)發(fā)機(jī)制的幾個(gè)步驟了腺逛,我們就不再重復(fù)說明了荷愕,接下來我們?cè)賮砜纯慈绾芜x擇我們的實(shí)現(xiàn)。

1)動(dòng)態(tài)決議

需要?jiǎng)討B(tài)實(shí)現(xiàn)這個(gè)未知的方法屉来,而且需要考慮到參數(shù)問題路翻,比較麻煩,不采用茄靠。

2)備用接收

將這個(gè)未知的方法轉(zhuǎn)交給其它對(duì)象,結(jié)果還是需要實(shí)現(xiàn)這個(gè)未知方法蝶桶,同上慨绳,不采用。

3)消息轉(zhuǎn)發(fā)

完整的消息轉(zhuǎn)發(fā)真竖,將未知的方法打包成一個(gè)NSInvocation轉(zhuǎn)交給別的對(duì)象脐雪,但我們?cè)趂orwardInvocation:完全可以不實(shí)現(xiàn)任何真的轉(zhuǎn)發(fā),就可以攔截掉這次的轉(zhuǎn)發(fā)恢共,所以采用這種方式最合適战秋。

在實(shí)現(xiàn)的時(shí)候,我們?cè)贛ethodSignature方法里讨韭,將方法簽名指向一個(gè)我們自定義的類的方法脂信,并且拿到簽名,返回給系統(tǒng)透硝。在forwardInvocation里狰闪,不做任何實(shí)現(xiàn)就可以了。

5.子線程初始化UIView導(dǎo)致的崩潰濒生。

這種情況也比較簡(jiǎn)單埋泵,就是把UIView的初始化方法及addSubview的方法交換一下,然后判斷一下當(dāng)前線程是不是主線程,如果不是主線程丽声,那么GCD到主線程里實(shí)現(xiàn)就行了礁蔗。

6.KVO的重復(fù)添加、刪除雁社,或者忘了刪除導(dǎo)致的崩潰浴井。

KVO出現(xiàn)最多的崩潰可能就是忘記刪除或者重復(fù)刪除了,要解決這個(gè)問題歧胁,最簡(jiǎn)單的實(shí)現(xiàn)就是記錄每次添加的observer和keyPath滋饲,所以我在addObserver:forKeyPath:options:context:這個(gè)方法里新建了一個(gè)字典,用來記錄observer和keyPath喊巍。

下面需要解決的就是什么時(shí)候去調(diào)用的問題屠缭,我首先想到的是在dealloc時(shí)去判斷是否添加了KVO的監(jiān)視,但是當(dāng)我直接交換了dealloc方法后發(fā)現(xiàn)崭参,這個(gè)方法調(diào)用的太多了呵曹,并不適合直接交換,不然整個(gè)程序都會(huì)卡頓起來何暮,需要找一個(gè)時(shí)機(jī)奄喂,于是我又修改為在添加監(jiān)視的時(shí)候去交換dealloc,這次成功了海洼,這樣可以減少對(duì)不必要的類進(jìn)行方法交換跨新,同時(shí)提高效率。

唯一需要注意的是在ARC的情況下坏逢,不能直接@selector(dealloc)來做方法交換域帐,需要變形一下NSSelectorFromString(@"dealloc"),這樣才能做方法交換是整。

完整Demo地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肖揣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子浮入,更是在濱河造成了極大的恐慌龙优,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件事秀,死亡現(xiàn)場(chǎng)離奇詭異彤断,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秽晚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門瓦糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赴蝇,你說我怎么就攤上這事菩浙。” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵劲蜻,是天一觀的道長(zhǎng)陆淀。 經(jīng)常有香客問我,道長(zhǎng)先嬉,這世上最難降的妖魔是什么轧苫? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮疫蔓,結(jié)果婚禮上含懊,老公的妹妹穿的比我還像新娘。我一直安慰自己衅胀,他們只是感情好岔乔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滚躯,像睡著了一般雏门。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掸掏,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天茁影,我揣著相機(jī)與錄音,去河邊找鬼丧凤。 笑死募闲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的愿待。 我是一名探鬼主播蝇更,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼呼盆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蚁廓,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤访圃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后相嵌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腿时,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年饭宾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了批糟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡看铆,死狀恐怖徽鼎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤否淤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布悄但,位于F島的核電站,受9級(jí)特大地震影響石抡,放射性物質(zhì)發(fā)生泄漏檐嚣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一啰扛、第九天 我趴在偏房一處隱蔽的房頂上張望嚎京。 院中可真熱鬧,春花似錦隐解、人聲如沸鞍帝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膜眠。三九已至,卻和暖如春溜嗜,著一層夾襖步出監(jiān)牢的瞬間宵膨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工炸宵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辟躏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓土全,卻偏偏與公主長(zhǎng)得像捎琐,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子裹匙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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