[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[x]

在iOS开发中我们经常初始化一个字典用如下方法

NSString * firstString ;
    NSString * secondString = @"hahha";
    NSDictionary * dict = @{@"1":firstString,@"2":secondString};

如果firstString 没有赋值,那么可能就会抱错,错误为

'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[x]_第1张图片
字典初始化错误

最好的结局办法是将firstString赋初始值,但是如果项目中

BUT

但是,但是,但是,如果在开发的过程中突然发现由于某些原因导致很多地方字典的初始化的时候Value都是nil,那么怎么办呢?**

博主在此提供两个解决问题的方法

解决方法一

采用运行时机制,我们都知道oc是基于运行时的,不要一听到运行时,就被吓到了---- 没有什么是努力和勤奋解决不了的问题,只要肯下功夫。

// 这里是一个NSDictionary的分类 
@implementation NSDictionary (AL)

+ (void)load {
    NSLog(@"dajiahao====== %s",__func__);
    Method fromMethod = class_getInstanceMethod(objc_getClass("__NSPlaceholderDictionary"), @selector(initWithObjects:forKeys:count:));
    Method toMethod = class_getInstanceMethod(objc_getClass("__NSPlaceholderDictionary"), @selector(st_initWithObjects:forKeys:count:));
    method_exchangeImplementations(fromMethod, toMethod);
}

+(void)initialize
{
    NSLog(@"hahha ====== %s",__func__);
}

/*
 **/
-(instancetype)st_initWithObjects:(id *)objects forKeys:(id *)keys count:(NSUInteger)count {
    NSUInteger rightCount = 0;
    for (NSUInteger i = 0; i < count; i++) {
        // 这里只做value 为nil的处理 对key为nil不做处理
        if (objects[i] == nil) {
          objects[i] = [NSNull null]  ; //有看到很多人这个地方判断了objects 和keys 如果它们中有一个为nil 那么就直接break ,但是我个人不太建议使用key的值nil的时候直接break。
// objects[i] = @"" ; 也可以根据个人情况这样写 
        }
        rightCount++;
    }
    return  [self st_initWithObjects:objects forKeys:keys count:rightCount];
}

苹果推荐 NSDictionary * dict = @{@"1":firstString,@"2":secondString};这种方法初始化数组的原因就是告诉你values的值为nil,所以crash了,所以我个人更倾向于如果values的值为nil,那么给它赋一个值(谨代表个人理解)

⚠️ 注意

  objects[i] = [NSNull null]  和objects[i] = @""  还是有区别的,可以log出来

e.g. 从上初始化例子log得出以下:

使用objects[i] = [NSNull null] 的log为
[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[x]_第2张图片
屏幕快照 2017-08-03 19.26.45.png
objects[i] = @"" 的log为
屏幕快照 2017-08-03 19.27.19.png

那么就会有人问,既然两种方法都可以使用,那么改选者那种方法好呢?

其实这个问题也是很好回答的,我更建议使用objects[i] = [NSNull null] 这种方法。

未完待续

你可能感兴趣的:([__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[x])