>>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有值:<null>
//第二句条件显然不成立,list == [NSNull null]并不等于nil,故没有打印
2017-01-19 16:01:14.411 [10440:154188] 服务器返回的dic[list]=<null>,其类型:NSNull
2017-01-19 16:01:14.412 [10440:154188] list就是单例[NSNull null]
2017-01-19 16:01:14.412 [10440:154188] 服务器返回的dic[list]=<null>,其类型: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即可。谷歌一下,会有很多答案。