2009-09-22 39 views
18

Có cách nào để truy cập phần tử NSArray với valueForKeyPath không? Ví dụ, dịch vụ mã hóa địa lý đảo ngược của Google trả về một cấu trúc dữ liệu rất phức tạp. Nếu tôi muốn có được thành phố, ngay bây giờ tôi phải phá vỡ nó thành hai cuộc gọi, như thế này:Lấy các phần tử mảng có giá trịForKeyPath

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

Chỉ cần tự hỏi nếu có một cách để bót đi giày gọi objectAtIndex: vào valueForKeyPath chuỗi. Tôi đã thử một công thức javascript-esque như @ "Placemark [0] .address" nhưng không có con xúc xắc.

Trả lời

17

Thật không may, không. Tài liệu đầy đủ về những gì được cho phép sử dụng Mã hóa khóa-giá trị là here. Không, theo hiểu biết của tôi, bất kỳ toán tử nào cho phép bạn lấy một mảng hoặc đối tượng được đặt cụ thể.

+0

Bạn có thể lấy một mảng cụ thể. Không chắc chắn về việc nhận được một phần tử mảng. Xem http://stackoverflow.com/questions/3165290/how-to-parsing-json-object-in-iphone-sdk-xcode-using-json-framework – Fraggle

+2

Vui lòng cập nhật liên kết trong câu trả lời này, trang không còn tồn tại . – ZeMoon

+0

Đã cập nhật liên kết. – codehearted

15

Dưới đây là một loại tôi chỉ viết cho NSObject có thể xử lý chỉ số mảng, do đó bạn có thể truy cập một đối tượng lồng nhau như thế này: "person.friends [0] .name"

@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 

Sử dụng nó như vậy

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

Không có kiểm tra lỗi, do đó, nó dễ bị phá vỡ nhưng bạn có ý tưởng.

+4

Loại không liên quan bây giờ mà chúng tôi có cú pháp chữ Obj-C cải tiến. Bạn có thể viết câu lệnh gốc trong câu hỏi của tôi dưới dạng 'NSDictionary * address = dictionary [@" Dấu vị trí "] [0] [@" address "];' – jsd

+2

Yea cú pháp mới rất tuyệt. Tôi đang sử dụng ví dụ của tôi ở trên trong một kịch bản mà một cấu trúc dữ liệu bên ngoài có thể thay đổi, do đó, một bộ chọn chuỗi rất hữu ích. – psy

+0

@jsd Đôi khi nó có thể hữu ích khi được sử dụng với Cocoa Bindings hoặc với các toán tử như '@ sum'. Đặc biệt khi được sử dụng với các nhãn gỡ lỗi tạm thời. –

3

Bạn có thể chặn đường phím trong đối tượng đang giữ NSArray.

Trong trường hợp của bạn, đường phím sẽ trở thành Dấu vị trí0.address ... Giá trị ghi đèForUndefinedKey; tìm chỉ mục trong đường phím; một cái gì đó như thế này:

-(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]; 
} 

Điều này hoạt động thực sự tốt cho khuôn khổ mô hình ví dụ: Mantle.

Các vấn đề liên quan