如果我有一个通常来自解析的 JSON 对象的大型 NSDirectory,我可以使用如下代码访问该对象:
[[[[[obj objectForKey:@"root"] objectForKey:@"key1"] objectAtIndex:idx] objectForKey:@"key2"] objectAtIndex:idz];
这条线可能比这长得多。
我可以以任何方式优化此代码吗?至少让它更容易阅读?
如果对象不对应,这一行也会产生运行时错误,避免这种情况的最有效方法是什么?
如果我有一个通常来自解析的 JSON 对象的大型 NSDirectory,我可以使用如下代码访问该对象:
[[[[[obj objectForKey:@"root"] objectForKey:@"key1"] objectAtIndex:idx] objectForKey:@"key2"] objectAtIndex:idz];
这条线可能比这长得多。
我可以以任何方式优化此代码吗?至少让它更容易阅读?
如果对象不对应,这一行也会产生运行时错误,避免这种情况的最有效方法是什么?
如果您正在使用-objectForKey:
您可以使用的所有内容-valueForKeyPath:
,例如
[obj valueForKeyPath:@"key1.key2.key3.key4"]
但是,当您需要使用-objectAtIndex:
. 我不认为有什么好的解决方案适合你。-valueForKeyPath:
也不会解决运行时错误的问题。
如果你真的想要一个简单的方法来做到这一点,你可以编写你自己的版本-valueForKeyPath:
(称它为别的),它提供了一种用于指定一个-objectAtIndex:
而不是键的语法,并进行适当的动态检查以确保对象实际响应有问题的方法。
如果你想更容易阅读代码,你可以像这样将该行分成几行
MyClass *rootObject = [obj objectForKey:@"root"];
MyClass *key1Object = [rootObject objectForKey:@"key1"];
MyClass *myObject = [key1Object objectAtIndex:idx];
...
等等。
我认为,您可以创建一些数组,该数组将包含您的对象的完整“路径”。唯一的事情是,您需要以某种方式存储索引,可能在 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 所说,如果没有索引,可以使用键值编码。
不知道是否适合你,不过你也可以试试积木,我总觉得很方便。至少他们使代码更具可读性。
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];