最近项目中经常出现下面的这个崩溃信息,经多方查找发现,是nil指针对NSDictionary及NSArray初始化的影响,所以做了以下记录,供以后自己查看.
-[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]
第一:正常使用字典的时候
NSString *value1 =@"value001";
NSString *value2 =@"value002222";
NSString *value3 =@"value003";
NSDictionary *dic = [[NSDictionary alloc]initWithObjectsAndKeys:value1,@"key1",value2,@"key02",value3,@"key3", nil] ;
NSLog(@"%@",dic);
输出结果:
demo[25109:378863] {
key02 = value002222;
key1 = value001;
key3 = value003;
}
第二:当插入的数据有空值的时候,系统会阻止你向object[1]插入一个nil指针
NSString *value1 =@"value001";
NSString *value2 =nil;
NSString *value3 =@"value003";
NSDictionary *dic = [[NSDictionary alloc]initWithObjectsAndKeys:value1,@"key1",value2,@"key02",value3,@"key3", nil] ;
NSLog(@"%@",dic);
输出结果:
demo[25139:383616] {
key1 = value001;
}
第三:当使用快速创建字典的时候
NSString *value1 =@"value001";
NSString *value2 =nil;
NSString *value3 =@"value003";
NSDictionary *dic =@{@"key1":value1,@"key2":value2,@"key3":value3};
NSLog(@"%@",dic);
运行改程序,会出现下面的崩溃错误信息
reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]'
第四:使用快速创建字典 解决崩溃方法 nil用[NSNull null]代替
NSString *value1 =@"value001";
NSString *value2 =[NSNull null];
NSString *value3 =@"value003";
NSDictionary *dic
=@{@"key1":value1,@"key2":value2,@"key3":value3};
NSLog(@"%@",dic);
输出结果:{
key1 = value001;
key2 = "<null>";
key3 = value003;
}
同理,使用NSArray时也应该注意这类问题。这里不再演示.但是model类型的是否会出现以下问题呢?我们来看一个例子:
NSMutableArray *mutArr = [[NSMutableArray alloc]init];
People *p = [[People alloc]init];
p.name =@"Allison";
p.sex = nil;
p.address = @"美国";
p.love = @"蔬菜";
[mutArr addObject:p];
输出结果:
demo[1777:90414] Allison-(null)-美国-蔬菜
可以看到,这里并不会引起崩溃,p.sex = nil并不会引起崩溃,因为这里添加到数组里面的是p对象,而不是p.sex这个属性,如果我们是[mutArr addObject:p.sex];运行发现出现了一样的崩溃信息eason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
但是我总觉得这不是最好的解决方法,因为苹果既然出了这个快速创建字典的方法,就说明程序员使用的几率还是比较高的,因为我们有时候add一个对象,并没有判断是否为nil ,所以如果因为粗心,造成这样的崩溃,就不好了.所以对于这个问题,我觉得最好办法还是应该从根本上解决问题,所以写了个类别来解决.
NSMutableArray的类别:
NSMutableDictionary的类别:
我们来验证一下,比如刚刚这个例子
例1:关于数组
NSMutableArray *mutArr = [[NSMutableArray alloc]init];
People *p = [[People alloc]init];
p.name =@"Allison";
p.sex = nil;
p.address = @"美国";
p.love = @"蔬菜";
[mutArr addSafeObject:p.sex];
输出结果:
Printing description of mutArr:
<__NSArrayM 0x608000058f60>(
)
这里数组就是空,并没有引起崩溃.
例2: 关于字典
NSString *value1 =@"value001";
NSString *value2 =nil;
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionaryWithCapacity:0];
[mutableDic setValue:value1 forKey:@"key1"];
[mutableDic setIfNilObject:value2 forKey:@"key2"];
NSLog(@"%@",mutableDic);
输出结果:
{
key1 = value001;
key2 = "<null>";
}
这里使用了setIfNilObject,可以向字典中插入控制,并没有引起崩溃.