ios项目从NSArray/NSDictionary/NSSet取出对象为[NSNull null]导致崩溃问题

>>Objective-C的集合对象,如NSArray、NSDictionary、NSSet等,是允许包含NSNull对象(即[NSNull null]),经常从服务器请求下来的json中包含null时,NSJSONSerialization解析时自动把null换成[NSNull null]。

**
例如:通过AFN从服务器请求下来的json数据显示为 { "list" : null },当AFN通过NSJSONSerialization解析成OC字典dic时,会自动把null换成[NSNull null]空对象(单例),即转化后dic = @{ @"list" : [NSNull null] },而我们在对空对象发送任何对象消息(-开头方法)时,都会报错。
因为NSNull类只有一个+ (NSNull *)null;类方法,没有任何对象方法。报错通常为:-[NSNull count]: unrecognized selector sent to instance 0x10c684fb0之类
**

最近在项目中踩过一次大坑,如下是一段测试代码

id list = dic[@"list"];

if (list) {
    NSLog(@"list有值:%@",list);
}

if (list == nil) { //等价于 if(!list)
    NSLog(@"list == nil对象指针为nil");
}

if (list == [NSNull null]) { //[NSNull null]为单例,故所有NSNull类型的指针,全等于[NSNull null]
    NSLog(@"list就是单例[NSNull null]");
}

if ([list isKindOfClass:[NSNull class]]) {  /* list表面为id,实际为NSNull类型,
                                             isKindOfClass是运行时方法,判断的是对象的真实类型*/
    NSLog(@"服务器返回的dic[list]=%@,其类型:%@",dic[@"list"],[dic[@"list"] class]);
}

if ([dic[@"list"] isKindOfClass:[NSNull class]]) {
    NSLog(@"服务器返回的dic[list]=%@,其类型:%@",dic[@"list"],[dic[@"list"] class]);
}

/*[aArr arrayWithArray:bArr]内部会将bArr遍历,类似for(int i = 0; i < bArr.count; i++){},
 此时bArr实际是[NSNull null]空对象(一个对象方法都没有),故会找不到count方法。*/
NSMutableArray *listArrM = [NSMutableArray arrayWithArray: dic[@"list"]];

打印结果如下:

2017-01-19 16:01:14.411 [10440:154188] list有值:
//第二句条件显然不成立,list == [NSNull null]并不等于nil,故没有打印
2017-01-19 16:01:14.411 [10440:154188] 服务器返回的dic[list]=,其类型:NSNull
2017-01-19 16:01:14.412 [10440:154188] list就是单例[NSNull null]
2017-01-19 16:01:14.412 [10440:154188] 服务器返回的dic[list]=,其类型:NSNull
2017-01-19 16:01:14.447 [10440:154188] -[NSNull count]: unrecognized selector sent to instance 0x10c684fb0

关于NSNull导致的报错解决起来也比较简单,可通过isKindOfClass:[NSNull class]来判断,进行单次错误拦截。也可以通过给NSNull增加分类的方式,将整个项目中,即将发生[NSNull null]无此方法的报错全部拦截,将空对象替换为nil即可。谷歌一下,会有很多答案。

你可能感兴趣的:(ios项目从NSArray/NSDictionary/NSSet取出对象为[NSNull null]导致崩溃问题)