問題描述
在服務(wù)器返回 json 數(shù)據(jù)的時候逐抑,時常會出現(xiàn)如下數(shù)據(jù)
"somevalue":null
通過JsonKit 這個第三方庫解析出來的數(shù)據(jù)就成了
somevalue = "<null>";
這個數(shù)據(jù)類型不是nil 也不是 String第焰,而是NSNull 的對象咽袜。 如果直接向這個對象發(fā)送消息就會直接崩潰。提示錯誤為:
-[NSNulllength]: unrecognized selector sent to instance 0x388a4a70
解決方法
1驮吱、最開始的解決方法就是為了應(yīng)付當(dāng)前遇到的崩潰茧妒,看看哪個字段可能為空,那么就對該字段使用前進行判斷左冬,通過崩潰時的錯誤提示可以看出桐筏,這樣的字段解析成的對象是 NSNull 類型的,所以可以直接判斷是不是此類型:
if(![isKindOfClass:[NSNullclass]]){xxxxxxx;}
但是無法對每個字段逐一進行該操作拇砰,所以這種辦法僅適用于判斷特定字段梅忌。
2、用字符串匹配null并進行替換除破。在獲取到服務(wù)器返回的Json時牧氮,返回結(jié)果時string對象,于是就先替換 null 為 為空字符””瑰枫,然后再解析踱葛。
json = [jsonStr
stringByReplacingOccurrencesOfString:@":null"withString:@":"""];
這個方法可以寫成NSString的category,然后調(diào)用相應(yīng)方法即可光坝,相對簡潔尸诽,但是如果要對string,array盯另,dictionary都進行判斷性含,也是不小的工作量。而且服務(wù)器的數(shù)據(jù)格式也不能保證鸳惯,也許會匹配不上商蕴。
3、最后沒有辦法芝发,只能在解析的時候下手绪商,把是NSNull 類型的值替換成nil。 一般就寫個tool方法辅鲸,然后解析時調(diào)用格郁。但是嫌太麻煩,就想弄寫個宏,通過搜索驚奇的發(fā)現(xiàn)宏也是可以有返回值的理张,結(jié)果如下:
#define VerifyValue(value)
({idtmp;
if([value isKindOfClass:[NSNullclass]])
tmp =nil;
else
tmp = value;
tmp;
})
宏里的最后一句語句便是返回值。然后在解析數(shù)據(jù)時調(diào)用宏:
contact.contactPhone = VerifyValue(contactDic[@"send_ContactPhone"]);
這個方法其實和方法三是類似的思想绵患。
4雾叭、如果你使用AFNetwork 這個庫做網(wǎng)絡(luò)請求,可以用以下代碼去掉這個討厭的空值
((AFJSONResponseSerializer*)manager.responseSerializer).removesKeysWithNullValues=YES;
經(jīng)過如上設(shè)置落蝙,所有 NSNull 的值织狐,都變成了 nil。
5筏勒、NullSafe
githhub上有一個Category移迫,叫做NullSafe ,可以在運行時操作管行,把空值置為nil厨埋,而nil是安全的,可以向nil對象發(fā)送任何message而不會奔潰捐顷。這個category使用起來非常方便荡陷,只要把NullSafe.m加入到工程中就可以了,無需做其他操作迅涮,NullSafe會在運行時自動加載废赞。詳細(xì)的請去Github上查看:NullSafe
這里還有一個極簡的封裝方法:
#import"NSNull+OVNatural.h"
@implementationNSNull(OVNatural)
- (void)forwardInvocation:(NSInvocation *)invocation
{
if([selfrespondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:self];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature *sig = [[NSNull class] instanceMethodSignatureForSelector:selector];
if(sig ==nil) {
sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"];
}
returnsig;
}
@end
關(guān)于[NSMethodSignature signatureWithObjCTypes:“@^vc”]的功能
可以參考以下兩篇文章
Objective-C Runtime Programming Guide
Type Encodings
文中方法源自在網(wǎng)上看到的多種方法的整理,加入了一定自己的理解叮姑。如果有原創(chuàng)者看到麻煩告訴我唉地,我會加上原博地址或者刪除。