2

如果我有一个通常来自解析的 JSON 对象的大型 NSDirectory,我可以使用如下代码访问该对象:

[[[[[obj objectForKey:@"root"] objectForKey:@"key1"] objectAtIndex:idx] objectForKey:@"key2"] objectAtIndex:idz];

这条线可能比这长得多。

我可以以任何方式优化此代码吗?至少让它更容易阅读?

如果对象不对应,这一行也会产生运行时错误,避免这种情况的最有效方法是什么?

4

4 回答 4

4

如果您正在使用-objectForKey:您可以使用的所有内容-valueForKeyPath:,例如

[obj valueForKeyPath:@"key1.key2.key3.key4"]

但是,当您需要使用-objectAtIndex:. 我不认为有什么好的解决方案适合你。-valueForKeyPath:也不会解决运行时错误的问题。

如果你真的想要一个简单的方法来做到这一点,你可以编写你自己的版本-valueForKeyPath:(称它为别的),它提供了一种用于指定一个-objectAtIndex:而不是键的语法,并进行适当的动态检查以确保对象实际响应有问题的方法。

于 2012-07-04T08:21:35.323 回答
0

如果你想更容易阅读代码,你可以像这样将该行分成几行

 MyClass *rootObject = [obj objectForKey:@"root"];
 MyClass *key1Object = [rootObject objectForKey:@"key1"];
 MyClass *myObject = [key1Object objectAtIndex:idx];
 ...

等等。

于 2012-07-04T08:13:34.030 回答
0

我认为,您可以创建一些数组,该数组将包含您的对象的完整“路径”。唯一的事情是,您需要以某种方式存储索引,可能在 NSNumber 中,在这种情况下,您不能使用 NSNumber 对象作为字典中的键。然后创建一个方法,该方法将为这个给定的“路径”返回所需的对象。喜欢

NSMutableArray* basePath = [NSMutableArray arrayWithObjects: @"first", [NSNumber numberWithInt:index], nil];
id object = [self objectForPath:basePath inContainer:container];

- (id) objectForPath:(NSMutableArray*)basePath inContainer:(id)container
{
    id result = nil;
    id pathComponent = [basePath objectAtIndex: 0];
    [basePath removeObjectAtIndex: 0];

    // check if it is a number with int index
    if( [pathComponent isKindOfClass:[NSNumber class]] ) 
    {
        result = [container objectAtIndex: [pathComponent intValue]];
    }
    else
    {
        result = [container objectForKey: pathComponent];
    }

    assert( result != nil );

    // check if it is need to continue searching object
    if( [basePath count] > 0 )
    {
        return [self objectForPath:basePath inContainer: result];
    }
    else
    {
        return result;
    }
}

这只是一个想法,但我希望你明白我的意思。并且正如上面 Kevin 所说,如果没有索引,可以使用键值编码。

于 2012-07-04T08:29:10.080 回答
0

不知道是否适合你,不过你也可以试试积木,我总觉得很方便。至少他们使代码更具可读性。

NSArray *filter = [NSArray arrayWithObjects:@"pathToFind", @"pathToFind2",nil];

NSPredicate *filterBlock = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind){        
    NSArray *root = (NSArray*)obj;

    // cycle the array and found what you need.
    // eventually implementing some sort of exit strategy

}];

[rootObject filteredArrayUsingPredicate:filterBlock];
于 2012-07-04T08:36:33.263 回答