Подтвердить что ты не робот

Получение элементов массива с помощью valueForKeyPath

Есть ли способ получить доступ к элементу NSArray с помощью valueForKeyPath? Служба обратного геокодирования Google, например, возвращает очень сложную структуру данных. Если я хочу получить город, прямо сейчас я должен разбить его на два вызова, например:

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

Просто интересно, есть ли способ перекодировать вызов objectAtIndex: в строку valueForKeyPath. Я пробовал формулировку javascript-esque, например @ "Placemark [0].address", но не кубик.

4b9b3361

Ответ 1

К сожалению, нет. Полная документация на то, что позволяет использовать кодирование с ключом, здесь. По-моему, не существует никаких операторов, которые позволят вам захватить определенный массив или заданный объект.

Ответ 2

Здесь категория, которую я только что написал для NSObject, которая может обрабатывать индексы массивов, чтобы вы могли получить доступ к вложенному объекту, подобному этому: "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

Используйте его так

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

Нет проверки ошибок, поэтому она подвержена взлому, но вы получаете идею.

Ответ 3

Вы можете перехватить путь ключа в объекте, содержащем NSArray.

В вашем случае ключ-путь станет Placemark0.address... Override valueForUndefinedKey; искать индекс в ключевом пути; что-то вроде этого:

-(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.