做過iOS開發(fā)的,在開始的時(shí)候一定會(huì)遇到這樣的問題,明明代碼寫的好好的,但是有時(shí)候莫名其妙的程序就崩潰了,然后下全局?jǐn)帱c(diǎn)發(fā)現(xiàn),很多時(shí)候是因?yàn)榉?wù)器返回的字段為null,導(dǎo)致空指針,從而導(dǎo)致程序崩潰。這時(shí),會(huì)想各種方法解決。接下來給各位介紹三種我使用的方法。
最近發(fā)現(xiàn)一個(gè)比較好的解決方法:
第一種方法
前提是你用的是AFNetworking第三方。
設(shè)置下面屬性:
serializer.removesKeysWithNullValues = YES;
在哪里設(shè)置呢?搜索AFURLResponseSerialization.m類,在定位到AFJSONResponseSerializer類,如下圖:

然后定位:AFJSONObjectByRemovingKeysWithNullValues
static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject,NSJSONReadingOptions readingOptions) {
if ([JSONObject isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
for (id value in (NSArray *)JSONObject) {
[mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
}
return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
} else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
id value = (NSDictionary *)JSONObject[key];
if (!value || [value isEqual:[NSNull null]]) {
//這里是本庫作者的源代碼
//[mutableDictionary removeObjectForKey:key];
//下面是改動(dòng)后的,將空指針類型改為空字符串
mutableDictionary[key] = @"";
} else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions);
}
}
return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
}
return JSONObject;
}
修改部分就是將空指針value改為空字符串。
如果你沒有用AFN也沒有關(guān)系下面我們來看看這個(gè)終極解決的辦法:
第二種方法:
這是一個(gè)一勞永逸的方案,牛逼的老外寫了一個(gè)Category,叫做NullSafe ,在運(yùn)行時(shí)操作,把這個(gè)討厭的空值置為nil,而nil是安全的,可以向nil對(duì)象發(fā)送任何message而不會(huì)奔潰。這個(gè)category使用起來非常方便,只要加入到了工程中就可以了,你其他的什么都不用做,對(duì),就是這么簡單。詳細(xì)的請(qǐng)去Github上查看;
解壓文件之后,直接將NullSafe.m文件導(dǎo)入到項(xiàng)目中就行了。
https://github.com/nicklockwood/NullSafe

但是第二種方法不知道是不是已經(jīng)有AFNetworking的緣故,我自行倒入后發(fā)現(xiàn)沒有效果,可能是和AFNetworking沖突的緣故吧。
第三種方法
自己寫一個(gè)工具類NullClean,集成自NSObject,將所有的null變成@"",
代碼如下:
NullClean.h中申明一個(gè)方法,以便于外界調(diào)用
+(id)changeType:(id)myObj;
接下來在NullClean.m中實(shí)現(xiàn)
#pragma mark - 公有方法
//類型識(shí)別:將所有的NSNull類型轉(zhuǎn)化成@""
+(id)changeType:(id)myObj
{
if ([myObj isKindOfClass:[NSDictionary class]])
{
return [self nullDic:myObj];
}
else if([myObj isKindOfClass:[NSArray class]])
{
return [self nullArr:myObj];
}
else if([myObj isKindOfClass:[NSString class]])
{
return [self stringToString:myObj];
}
else if([myObj isKindOfClass:[NSNull class]])
{
return [self nullToString];
}
else
{
return [NSString stringWithFormat:@"%@",myObj];//此處都轉(zhuǎn)成了string類型,后期特殊需要可以改
}
}
#pragma mark - 私有方法
//將NSDictionary中的Null類型的項(xiàng)目轉(zhuǎn)化成@""
+(NSDictionary *)nullDic:(NSDictionary *)myDic
{
NSArray *keyArr = [myDic allKeys];
NSMutableDictionary *resDic = [[NSMutableDictionary alloc]init];
for (int i = 0; i < keyArr.count; i ++)
{
id obj = [myDic objectForKey:keyArr[i]];
obj = [self changeType:obj];
[resDic setObject:obj forKey:keyArr[i]];
}
return resDic;
}
//將NSDictionary中的Null類型的項(xiàng)目轉(zhuǎn)化成@""
+(NSArray *)nullArr:(NSArray *)myArr
{
NSMutableArray *resArr = [[NSMutableArray alloc] init];
for (int i = 0; i < myArr.count; i ++)
{
id obj = myArr[i];
obj = [self changeType:obj];
[resArr addObject:obj];
}
return resArr;
}
//將NSString類型的原路返回
+(NSString *)stringToString:(NSString *)string
{
return string;
}
//將Null類型的項(xiàng)目轉(zhuǎn)化成@""
+(NSString *)nullToString
{
return @"";
}
在請(qǐng)求到數(shù)據(jù)之后直接將請(qǐng)求到的數(shù)據(jù)作為入?yún)ⅲ祷亟Y(jié)果就是清完null之后的數(shù)據(jù)了