2009-09-22 65 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