在iOS開發(fā)過程中經(jīng)常需要與服務(wù)器進(jìn)行數(shù)據(jù)通訊器一,Json就是一種常用的高效簡潔的數(shù)據(jù)格式。
問題現(xiàn)象
但是幾個(gè)項(xiàng)目下來一直遇到一個(gè)坑爹的問題强窖,程序在獲取某些數(shù)據(jù)之后莫名崩潰释树。其實(shí)很早就發(fā)現(xiàn)了原因:由于服務(wù)器的數(shù)據(jù)庫中有些字段為空,然后以Json形式返回給客戶端時(shí)就會(huì)出現(xiàn)這樣的數(shù)據(jù):
"somevalue":null
通過JsonKit 這個(gè)第三方庫解析出來的數(shù)據(jù)就成了
somevalue ="";
這個(gè)數(shù)據(jù)類型不是nil 也不是 String乡小。 解析成對(duì)象之后阔加,如果直接向這個(gè)對(duì)象發(fā)送消息(eg:length,count 等等)就會(huì)直接崩潰满钟。提示錯(cuò)誤為:
-[NSNulllength]: unrecognized selector sent to instance 0x388a4a70
解決方法
其實(shí)一直沒有找到完美的解決辦法胜榔,坑了我很久。
1湃番、最開始的解決方法就是為了應(yīng)付當(dāng)前遇到的崩潰夭织,看看哪個(gè)字段可能為空,那么就對(duì)該字段使用前進(jìn)行判斷吠撮,通過崩潰時(shí)的錯(cuò)誤提示可以看出尊惰,這樣的字段解析成的對(duì)象是 NSNull 類型的,所以可以直接判斷是不是此類型:
if(![isKindOfClass:[NSNullclass]]){xxxxxxx;}
因?yàn)樽侄螌?shí)在太多纬向,就找一個(gè)補(bǔ)一個(gè)择浊。
2、后來想徹底解決這問題逾条,就打算從數(shù)據(jù)源下手琢岩,其實(shí)應(yīng)該可以用正則表達(dá)式匹配這個(gè)null ,然后進(jìn)行替換师脂,奈何正則是我的硬傷啊担孔。于是就相出了一個(gè)山寨方法:字符串匹配。在獲取到服務(wù)器返回的Json時(shí)吃警,返回結(jié)果時(shí)string對(duì)象糕篇,于是就先替換 null 為 為空字符””,然后再解析酌心。
json = [jsonStr? stringByReplacingOccurrencesOfString:@":null"withString:@":\"\""];
這個(gè)方法本來很奏效拌消,但是我這里的服務(wù)器返回極不簡潔,各種垃圾數(shù)據(jù)(不吐槽這了)安券。墩崩。。反正這樣會(huì)導(dǎo)致json無法解析了侯勉。
3鹦筹、最后沒有辦法,只能在解析的時(shí)候下手址貌,把是NSNull 類型的值替換成nil铐拐。 一般就寫個(gè)tool方法徘键,然后解析時(shí)調(diào)用。但是嫌太麻煩遍蟋,就想弄寫個(gè)宏吹害,通過搜索驚奇的發(fā)現(xiàn)宏也是可以有返回值的,結(jié)果如下:
#define VerifyValue(value)\
({idtmp;\
if([value isKindOfClass:[NSNullclass]])\
tmp =nil;\
else\
tmp = value;\
tmp;\
})\
宏里的最后一句語句便是返回值匿值。然后在解析數(shù)據(jù)時(shí)調(diào)用宏:
contact.contactPhone = VerifyValue(contactDic[@"send_ContactPhone"]);
4赠制、如果你使用AFNetwork 這個(gè)庫做網(wǎng)絡(luò)請(qǐng)求的話,可以用以下代碼挟憔,自動(dòng)幫你去掉這個(gè)討厭的空值
self.removesKeysWithNullValues =YES;
5钟些、終極方案
終于找到了一勞永逸的方案,牛逼的老外寫了一個(gè)Category绊谭,叫做NullSafe 政恍,在運(yùn)行時(shí)操作,把這個(gè)討厭的空值置為nil达传,而nil是安全的篙耗,可以向nil對(duì)象發(fā)送任何message而不會(huì)奔潰。這個(gè)category使用起來非常方便宪赶,只要加入到了工程中就可以了宗弯,你其他的什么都不用做,對(duì)搂妻,就是這么簡單蒙保。詳細(xì)的請(qǐng)去Github上查看;