首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSManagedObject属性值的NSNull处理

NSManagedObject属性值的NSNull处理
EN

Stack Overflow用户
提问于 2012-02-04 10:28:24
回答 5查看 8.6K关注 0票数 35

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

代码语言:javascript
复制
    fight.winnerID = [dict objectForKey:@"winner"];

这将抛出一个NSInvalidArgumentException

代码语言:javascript
复制
"winnerID"; desired type = NSString; given type = NSNull; value = <null>;

我可以很容易地检查[NSNull null]的值并将其赋值为nil

代码语言:javascript
复制
fight.winnerID = [dict objectForKey:@"winner"] == [NSNull null] ? nil : [dict objectForKey:@"winner"];

但我认为这并不优雅,而且需要设置很多属性。

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

代码语言:javascript
复制
fight.round = [NSNumber numberWithUnsignedInteger:[[dict valueForKey:@"round"] unsignedIntegerValue]]

NSInvalidArgumentException现在是:

代码语言:javascript
复制
[NSNull unsignedIntegerValue]: unrecognized selector sent to instance

在这种情况下,我必须先处理[dict valueForKey:@"round"],然后才能将其设置为NSUInteger值。单行解决方案就消失了。

我尝试创建一个@try @catch块,但是一旦捕获到第一个值,它就跳过整个@try块,并且下一个属性被忽略。

有没有更好的方法来处理[NSNull null],或者让它变得完全不同但更简单?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-02-04 10:58:54

如果将其封装在宏中,可能会更容易一些:

代码语言:javascript
复制
#define NULL_TO_NIL(obj) ({ __typeof__ (obj) __obj = (obj); __obj == [NSNull null] ? nil : obj; })

然后你可以写一些类似这样的东西

代码语言:javascript
复制
fight.winnerID = NULL_TO_NIL([dict objectForKey:@"winner"]);

或者,您可以对字典进行预处理,并在尝试将其填充到托管对象之前用nil替换所有的NSNull

票数 67
EN

Stack Overflow用户

发布于 2012-02-05 00:15:11

好了,我今天早上刚醒来就有了一个很好的解决方案。这样如何:

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

代码语言:javascript
复制
NSMutableDictionary *rootDict = [NSJSONSerialization JSONObjectWithData:_receivedData options:NSJSONReadingMutableContainers error:&error];
...

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

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

从可变的leafDict中删除过滤后的属性:

代码语言:javascript
复制
[leafDict removeObjectsForKeys:[nullSet allObjects]];

现在,当您调用fight.winnerID = [dict objectForKey:@"winner"];时,winnerID将自动为(null)nil,而不是<null>[NSNull null]

与此无关,但我也注意到,在将字符串解析为NSNumber时,使用NSNumberFormatter会更好,我所做的方式是从空字符串获取integerValue,这给了我一个不想要的NSNumber of 0,而我实际上希望它为nil。

之前:

代码语言:javascript
复制
// when [leafDict valueForKey:@"round"] == nil
fight.round = [NSNumber numberWithInteger:[[leafDict valueForKey:@"round"] integerValue]]
// Result: fight.round = 0

之后:

代码语言:javascript
复制
__autoreleasing NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
fight.round = [numberFormatter numberFromString:[leafDict valueForKey:@"round"]];    
// Result: fight.round = nil
票数 8
EN

Stack Overflow用户

发布于 2012-02-04 11:25:38

在使用之前,我编写了几个类别方法来从JSON生成的字典或数组中剥离空值:

代码语言:javascript
复制
@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

如果标准的JSON解析库默认具有这种行为就好了--省略空对象几乎总是比将它们包含为NSNulls更可取。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9137920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档