2009-09-22 38 views
18

有什么方法可以用valueForKeyPath访问NSArray元素?例如,Google的反向地理编码器服务会返回非常复杂的数据结构。如果我想要得到的城市,现在我必须把它分成两个呼叫,像这样:使用valueForKeyPath获取数组元素

NSDictionary *address = [NSString stringWithString:[[[dictionary objectForKey:@"Placemark"] objectAtIndex:0] objectForKey:@"address"]]; 
NSLog(@"%@", [address valueForKeyPath:@"AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName"]); 

只是想知道,如果有鞋拔子的objectAtIndex:呼叫到valueForKeyPath字符串的方式。我尝试了像@“Placemark [0] .address”这样的javascript-esque表达式,但没有使用骰子。

回答

17

不幸的是,没有。使用键值编码允许的完整文档是here。据我所知,没有任何操作符可以让你获取特定的数组或对象。

+0

你可以抓住一个特定的数组。不知道获取数组元素。请参阅http://stackoverflow.com/questions/3165290/how-to-parsing-json-object-in-iphone-sdk-xcode-using-json-framework – Fraggle

+2

请更新此答案中的链接,页面不再存在。 – ZeMoon

+0

更新了链接。 – codehearted

15

这里有一个类我只是写了NSObject的,可以处理数组的索引,所以你可以访问这样一个嵌套的对象:“person.friends [0]。名称”

@interface NSObject (ValueForKeyPathWithIndexes) 
    -(id)valueForKeyPathWithIndexes:(NSString*)fullPath; 
@end 


#import "NSObject+ValueForKeyPathWithIndexes.h"  
@implementation NSObject (ValueForKeyPathWithIndexes) 

-(id)valueForKeyPathWithIndexes:(NSString*)fullPath 
{ 
    NSRange testrange = [fullPath rangeOfString:@"["]; 
    if (testrange.location == NSNotFound) 
     return [self valueForKeyPath:fullPath]; 

    NSArray* parts = [fullPath componentsSeparatedByString:@"."]; 
    id currentObj = self; 
    for (NSString* part in parts) 
    { 
     NSRange range1 = [part rangeOfString:@"["]; 
     if (range1.location == NSNotFound)   
     { 
      currentObj = [currentObj valueForKey:part]; 
     } 
     else 
     { 
      NSString* arrayKey = [part substringToIndex:range1.location]; 
      int index = [[[part substringToIndex:part.length-1] substringFromIndex:range1.location+1] intValue]; 
      currentObj = [[currentObj valueForKey:arrayKey] objectAtIndex:index]; 
     } 
    } 
    return currentObj; 
} 
@end 

使用它像这样

NSString* personsFriendsName = [obj valueForKeyPathsWithIndexes:@"me.friends[0].name"]; 

有没有错误检查,所以它很容易打破,但你明白了。

+4

现在我们有了改进的Obj-C文字语法,这种不相关的东西。你可以在我的问题中将原始语句写成'NSDictionary * address = dictionary [@“Placemark”] [0] [@“address”];' – jsd

+2

是的,新的语法很棒。我在上面的例子中使用了一个外部数据结构可能会改变的场景,所以字符串选择器是非常有用的。 – psy

+0

@jsd与Cocoa绑定一起使用或使用'@ sum'等操作符时,它有时可能会有用。特别是与临时调试标签一起使用时。 –

3

您可以拦截持有NSArray的对象中的keypath。

在你的情况下,keypath将成为Placemark0.address ... Override valueForUndefinedKey;寻找keypath中的索引;是这样的:

-(id)valueForUndefinedKey:(NSString *)key 
{ 
    // Handle paths like Placemark0, Placemark1, ... 
    if ([key hasPrefix:@"Placemark"]) 
    { 
     // Caller wants to access the Placemark array. 
     // Find the array index they're after. 
     NSString *indexString = [key stringByReplacingOccurrencesOfString:@"Placemark" withString:@""]; 
     NSInteger index = [indexString integerValue]; 

     // Return array element. 
     if (index < self.placemarks.count) 
      return self.placemarks[index]; 
    } 

    return [super valueForUndefinedKey:key]; 
} 

这个作品真的很好的模型框架,例如Mantle