1.NSInvalidArgumentException 異常
出現(xiàn)這種異常的原因一般是在不可以出現(xiàn)nil數(shù)據(jù)的時(shí)候傳入了nil,比如在創(chuàng)建NSDictionary的時(shí)候值傳入了nil就會(huì)出現(xiàn)這種崩潰錯(cuò)誤,如果必須傳空需要把nil對(duì)象轉(zhuǎn)成NSNull才可以確保不出現(xiàn)這種錯(cuò)誤,有3種方案可以解決該問(wèn)題,如下:
方案一:后臺(tái)在返回?cái)?shù)據(jù)的時(shí)候進(jìn)行校驗(yàn)吭练,對(duì)空值進(jìn)行處理。但是在項(xiàng)目中有些空值是有特殊的用途,此種方案不可行饺窿。
方案二:在轉(zhuǎn)換成NSDictionary的時(shí)候,對(duì)后臺(tái)返回的數(shù)據(jù)進(jìn)行校驗(yàn)移斩,把空值轉(zhuǎn)換成NSNull對(duì)象肚医。方案可行,但是需要對(duì)現(xiàn)有代碼做大的改動(dòng)向瓷,每次轉(zhuǎn)換的時(shí)候都需要進(jìn)行校驗(yàn)肠套,太麻煩。業(yè)務(wù)高速發(fā)展時(shí)期猖任,這樣做成本太高你稚。
方案三:有沒(méi)有一種無(wú)須改動(dòng)現(xiàn)有代碼又能解決該問(wèn)題呢?答案是有的,可以利用Objective-C的runtime來(lái)解決該問(wèn)題入宦。
NSDictionary插入nil對(duì)象會(huì)造成崩潰哺徊,但是插入NSNull對(duì)象是不會(huì)造成崩潰的,只要利用runtime的Swizzle Method把nil對(duì)象給轉(zhuǎn)換成NSNull對(duì)象就可以把該問(wèn)題給解決了乾闰。創(chuàng)建一個(gè)NSDictionary的類(lèi)別落追,利用runtime的Swizzle Method來(lái)替換系統(tǒng)的方法。源碼實(shí)現(xiàn)可以參考Glow團(tuán)隊(duì)封裝的NSDictionary+NilSafe(Github上可下載到), 現(xiàn)截取其中的部分代碼如下:
+ (instancetype)gl_dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
id safeObjects[cnt];
id safeKeys[cnt];
NSUInteger j = 0;
for (NSUInteger i = 0; i < cnt; i++) {
id key = keys[i];
id obj = objects[i];
if (!key) {
continue;
}
if (!obj) {
obj = [NSNull null];
}
safeKeys[j] = key;
safeObjects[j] = obj;
j++;
}
return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
}
2.data parameter is nil
NSJSONSerialization序列化的時(shí)候涯肩,傳入data為nil轿钠,造成的崩潰,這個(gè)問(wèn)題比較好解決病苗,在序列化的時(shí)候疗垛,統(tǒng)一加入判斷,判斷data是不是nil即可硫朦。
3.unrecognized selector sent to instance 0x15d23910
造成這條崩潰的原因贷腕,想必大家都比較熟悉了,就是一個(gè)類(lèi)調(diào)用了一個(gè)不存在的方法咬展,造成的崩潰泽裳。解決這樣的問(wèn)題,可以在寫(xiě)一個(gè)方法的時(shí)候破婆,判斷一下其類(lèi)的類(lèi)型涮总,不符合類(lèi)型的不讓其調(diào)用
4.SIGSEGV 異常
當(dāng)去訪問(wèn)沒(méi)有被開(kāi)辟的內(nèi)存或者已經(jīng)被釋放的內(nèi)存時(shí),就會(huì)發(fā)生這樣的異常祷舀。另外瀑梗,在低內(nèi)存的時(shí)候,也可能會(huì)產(chǎn)生這樣的異常裳扯,一般開(kāi)發(fā)中用到C語(yǔ)言呢的時(shí)候比較容易出現(xiàn)這種錯(cuò)誤抛丽,因?yàn)锳RC并不會(huì)對(duì)C語(yǔ)言進(jìn)行內(nèi)存管理,所以用C語(yǔ)言創(chuàng)建的對(duì)象一定要手動(dòng)Free
5.Can't add self as subview crash
造成這個(gè)崩潰的原因嚎朽,一種原因是在push或pop一個(gè)視圖的時(shí)候铺纽,并且設(shè)置了animated:YES,如果此時(shí)動(dòng)畫(huà)(animated)還沒(méi)有完成哟忍,這個(gè)時(shí)候,你在去push或pop另外一個(gè)視圖的時(shí)候陷寝,就會(huì)造成該異常锅很。
解決該異常最簡(jiǎn)單的方式是把a(bǔ)nimated設(shè)置為NO,但是很不友好凤跑,把系統(tǒng)自帶的動(dòng)畫(huà)效果給去掉了爆安。另外一種友好的方式就是通過(guò)runtime來(lái)進(jìn)行實(shí)現(xiàn)了,通過(guò)安全的方式仔引,確保當(dāng)有控制器正在進(jìn)行入椚硬郑或出棧時(shí)褐奥,沒(méi)有其他入棧或出棧操作
6.NSRangeException 異常
越界異常翘簇,一般就是數(shù)組越界或者字符串截取越界
7.SIGPIPE 異常
先解釋一下什么是SIGPIPE異常撬码,通俗一點(diǎn)的描述是這樣的:對(duì)一個(gè)端已經(jīng)關(guān)閉的socket調(diào)用兩次write,第二次write將會(huì)產(chǎn)生SIGPIPE信號(hào)版保,該信號(hào)默認(rèn)結(jié)束進(jìn)程呜笑。
那如何解決該問(wèn)題呢?對(duì)SIGPIPE信號(hào)可以進(jìn)行捕獲彻犁,也可將其忽略叫胁,對(duì)于iOS系統(tǒng)來(lái)說(shuō),只需要把下面這段代碼放在.pch文件中即可汞幢。
// 僅在 IOS 系統(tǒng)上支持 SO_NOSIGPIPE
#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
// We do not want SIGPIPE if writing to socket.
const int value = 1;
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(int));
#endif
8.SIGABRT 異常
這是一個(gè)讓程序終止的標(biāo)識(shí)驼鹅,會(huì)在斷言、app內(nèi)部森篷、操作系統(tǒng)用終止方法拋出输钩。通常發(fā)生在異步執(zhí)行系統(tǒng)方法的時(shí)候。如CoreData疾宏、NSUserDefaults等张足,還有一些其他的系統(tǒng)多線程操作。
注意:這并不一定意味著是系統(tǒng)代碼存在bug坎藐,代碼僅僅是成了無(wú)效狀態(tài)为牍,或者異常狀態(tài)。