4

我是来自 Python 世界的开发人员,习惯于使用异常。我在很多地方发现在这里使用异常并不是那么明智,并在需要时尽力转换为 NSErrors。但后来我遇到了这个:

NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
    // Memory management code omitted
    SomeModel *model = [[SomeModel alloc] init];
    model.attr1 = [[dict objectForKey:@"key1"] integerValue];
    model.attr2 = [[dict objectForKey:@"key2"] integerValue];
    model.attr3 = [[dict objectForKey:@"key3"] integerValue];
    model.attr4 = [[dict objectForKey:@"key4"] integerValue];

    [results addObject:model];
}

dict 中的某些对象包含 NSNull,这将导致“无法识别的选择器”异常。在那种情况下,我想完全放弃那个数据。我的第一直觉是将 for 块的全部内容包装到 @try-@catch 块中:

NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
    @try
    {
        SomeModel *model = [[SomeModel alloc] init];
        model.attr1 = [[dict objectForKey:@"key1"] integerValue];
        model.attr2 = [[dict objectForKey:@"key2"] integerValue];
        model.attr3 = [[dict objectForKey:@"key3"] integerValue];
        model.attr4 = [[dict objectForKey:@"key4"] integerValue];

        [results addObject:model];
    }
    @catch(NSException *exception)
    {
        // Do something
    }
}

但这是一个好方法吗?如果不对每个变量进行重复检查,我就无法提出解决方案,这真的很难看 IMO。希望有我没有想到的替代方案。提前致谢。

4

3 回答 3

3

正确的 Objective-C 方法是:

for (NSDictionary *dict in dicts)
{
    if (! [dict isKindOfClass:[NSDictionary class]])
        continue;
    // ...
}

在发送消息之前测试接收者是否可以响应消息是 Objective-C 中的典型模式。

另外,请注意,Objective-C 中的异常始终是程序员错误,不用于正常的执行流程。

于 2012-10-31T10:18:56.550 回答
1

许多人使用 NSDictionary 上的一个类别来处理这些情况:

- (id)safeObjectForKey:(id)aKey
{
  id obj = [self objectForKey:aKey];
  if ([obj isKindOfClass:[NSNull class]])
  {
    return nil;
  }

  return obj;
}

您仍然需要确保您的 dict 是一个实际的字典实例。

于 2012-10-31T11:03:12.197 回答
0

最后我决定使用 KVC 来解决这个问题。像这样的东西:

- (id)initWithPropertyDictionary:(NSDictionary *)dict
                     lookUpTable:(NSDictionary *)keyToProperty
{
    self = [self init];
    for (NSString *key in dict)
    {
        NSString *propertyName;
        if ([keyToProperty objectForKey:key])
            propertyName = [keyToProperty objectForKey:key];
        else
            propertyName = key;
        if ([[dict objectForKey:key] isKindOfClass:[NSNull class]])
        {
            [self release];
            return nil;
        }
        else
        {
            [self setValue:[dict objectForKey:key] forKey:propertyName];
        }
    }
}

这个解决方案的挫折是我必须将 NSNumber 用于我的属性,但对于 JSON 数据,浮点数和整数之间确实没有区别,所以这很好。

如果你真的想要原始类型,你可以将此方法与将这些 NSNumber 转换为适当类型的自定义设置器结合使用。

有了这个,您需要做的就是在将对象添加到数组之前检查 nil 。除了模型类,到处都干净得多。

感谢 jaydee3 启发我专注于改变模型类。

于 2012-11-02T06:52:15.380 回答