对NSManagedObject属性值进行NSNull处理

我为我的NSManagedObject属性设置值,这些值来自NSDictionary正确序列化从JSON文件。 我的问题是,当某些值是[NSNull null] ,我不能直接分配给属性:

  fight.winnerID = [dict objectForKey:@"winner"]; 

这将抛出一个NSInvalidArgumentException

 "winnerID"; desired type = NSString; given type = NSNull; value = <null>; 

我可以很容易地检查[NSNull null]的值,并分配nil

 fight.winnerID = [dict objectForKey:@"winner"] == [NSNull null] ? nil : [dict objectForKey:@"winner"]; 

但是我认为这不是很高雅,而且有很多属性需要设置。

而且,当处理NSNumber属性时,这变得更加困难:

 fight.round = [NSNumber numberWithUnsignedInteger:[[dict valueForKey:@"round"] unsignedIntegerValue]] 

NSInvalidArgumentException现在是:

 [NSNull unsignedIntegerValue]: unrecognized selector sent to instance 

在这种情况下,我必须先处理[dict valueForKey:@"round"]然后再创build它的NSUInteger值。 而一线解决scheme不见了。

我尝试了一个@try @catch块,但只要第一个值被捕获,它就会跳转整个@try块,并忽略下一个属性。

有没有更好的方法来处理[NSNull null]或者使这完全不同,但更容易?

如果你用macros包装它可能会更容易一些:

 #define NULL_TO_NIL(obj) ({ __typeof__ (obj) __obj = (obj); __obj == [NSNull null] ? nil : obj; }) 

那么你可以写一些类似的东西

 fight.winnerID = NULL_TO_NIL([dict objectForKey:@"winner"]); 

或者,你可以预先处理你的字典,并用nilreplace所有的NSNull ,甚至试图将其填充到pipe理对象中。

好吧,我今天早上刚刚醒来,有一个很好的解决scheme。 那这个呢:

序列化JSON使用选项来接收可变数组和字典:

 NSMutableDictionary *rootDict = [NSJSONSerialization JSONObjectWithData:_receivedData options:NSJSONReadingMutableContainers error:&error]; ... 

从leafDict获取一组具有[NSNull null]值的键:

 NSSet *nullSet = [leafDict keysOfEntriesWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id key, id obj, BOOL *stop) { return [obj isEqual:[NSNull null]] ? YES : NO; }]; 

从你的Mutable leafDict中删除过滤的属性:

 [leafDict removeObjectsForKeys:[nullSet allObjects]]; 

现在当你打电话给fight.winnerID = [dict objectForKey:@"winner"];<null>或者[NSNull null]相比,winnerID会自动变为(null)nil

不是相对于此,但我也注意到,当parsingstring到NSNumberFormatter时使用NSNumberFormatter更好,我做的是从一个零string获取integerValue ,这给了我一个不希望的NSNumber 0 ,当我真的想要它为零。

之前:

 // when [leafDict valueForKey:@"round"] == nil fight.round = [NSNumber numberWithInteger:[[leafDict valueForKey:@"round"] integerValue]] // Result: fight.round = 0 

后:

 __autoreleasing NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init]; fight.round = [numberFormatter numberFromString:[leafDict valueForKey:@"round"]]; // Result: fight.round = nil 

我写了几个类别的方法来从JSON生成的字典或数组中去除null之前使用:

 @implementation NSMutableArray (StripNulls) - (void)stripNullValues { for (int i = [self count] - 1; i >= 0; i--) { id value = [self objectAtIndex:i]; if (value == [NSNull null]) { [self removeObjectAtIndex:i]; } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) { if (![value respondsToSelector:@selector(setObject:forKey:)] && ![value respondsToSelector:@selector(addObject:)]) { value = [value mutableCopy]; [self replaceObjectAtIndex:i withObject:value]; } [value stripNullValues]; } } } @end @implementation NSMutableDictionary (StripNulls) - (void)stripNullValues { for (NSString *key in [self allKeys]) { id value = [self objectForKey:key]; if (value == [NSNull null]) { [self removeObjectForKey:key]; } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) { if (![value respondsToSelector:@selector(setObject:forKey:)] && ![value respondsToSelector:@selector(addObject:)]) { value = [value mutableCopy]; [self setObject:value forKey:key]; } [value stripNullValues]; } } } @end 

如果标准JSONparsing库默认具有这种行为,那将是非常好的 – 忽略null对象比将它们包含为NSNull几乎总是可取的。

另一种方法是

 -[NSObject setValuesForKeysWithDictionary:] 

在这种情况下,你可以做

 [fight setValuesForKeysWithDictionary:dict]; 

在头文件NSKeyValueCoding.h中,它定义了“值为NSNull的字典条目导致-setValue:nil forKey:key消息被发送到接收者。

唯一的缺点是你将不得不把字典中的任何键变成接收器中的键。 即

 dict[@"winnerID"] = dict[@"winner"]; [dict removeObjectForKey:@"winner"]; 

我被卡住了同样的问题,发现这个post,做了一个稍微不同的方式。只使用类别 –

为“NSDictionary”创build一个新的分类文件并添加这一个方法 –

 @implementation NSDictionary (SuperExtras) - (id)objectForKey_NoNSNULL:(id)aKey { id result = [self objectForKey:aKey]; if(result==[NSNull null]) { return nil; } return result; } @end 

稍后在代码中使用它,对于可以在其中具有NSNULL的属性,只需以这种方式使用它 –

 newUser.email = [loopdict objectForKey_NoNSNULL:@"email"]; 

而已