KVC: как проверить существующий ключ - PullRequest
2 голосов
/ 17 сентября 2009

Мне нужна небольшая помощь по KVC.

Несколько слов о рабочем контексте:

1) iPhone подключается (клиент) к веб-сервису для получения объекта,

2) Я использую JSON для передачи данных,

3) Если у клиента точно такое же сопоставление объектов, я могу перебрать NSDictionary из JSON для сохранения данных в постоянном хранилище (coreData). Для этого я использую этот фрагмент кода (предположим, что все данные являются NSString):

NSDictionary *dict = ... dictionary from JSON

NSArray *keyArray = [dict allKeys]; //gets all the properties keys form server

for (NSString *s in keyArray){

[myCoreDataObject setValue:[dict objectForKey:s] forKey:s];  //store the property in the coreData object 

}

Теперь моя проблема ....

4) Что произойдет, если сервер реализует новую версию объекта с 1 новым свойством Если я передаю данные клиенту, а клиент не находится на уровне сохраненной версии (это означает, что все еще используется «старое» сопоставление объектов), я попытаюсь присвоить значение для несуществующего ключа ... есть сообщение:

сущность "myOldObject" не совместима со значением кода для ключа "myNewKey"

Не могли бы вы подсказать, как проверить наличие ключа в объекте, чтобы, если ключ существует, я мог перейти к обновлению значения, избегая сообщения об ошибке?

Извините, если я немного запутался в объяснении моего контекста.

Спасибо

Dario

1 Ответ

3 голосов
/ 08 января 2010

Хотя я не могу придумать, как выяснить, какие ключи будет поддерживать объект, вы можете использовать тот факт, что когда вы устанавливаете значение для несуществующего ключа, поведение вашего объекта по умолчанию - , выдает исключение . Вы можете заключить вызов метода setValue:forKey: в блок @try / @catch для обработки этих ошибок.

Рассмотрим следующий код для объекта:

@interface KVCClass : NSObject {
    NSString *stuff;
}

@property (nonatomic, retain) NSString *stuff;

@end

@implementation KVCClass

@synthesize stuff;

- (void) dealloc
{
    [stuff release], stuff = nil;

    [super dealloc];
}

@end

Это должно быть KVC-совместимым для ключа stuff, но не более.

Если вы обращаетесь к этому классу из следующей программы:

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    KVCClass *testClass = [[KVCClass alloc] init];

    [testClass setValue:@"this is the value" forKey:@"stuff"];

    NSLog(@"%@", testClass.stuff);

    // Error handled nicely
    @try {
        [testClass setValue:@"this should fail but we will catch the exception" forKey:@"nonexistentKey"];
    }
    @catch (NSException * e) {
        NSLog(@"handle error here");
    }

    // This will throw an exception
    [testClass setValue:@"this will fail" forKey:@"nonexistentKey"];

    [testClass release];
    [pool drain];
    return 0;
}

Вы получите консольный вывод, подобный следующему:

2010-01-08 18:06:57.981 KVCTest[42960:903] this is the value
2010-01-08 18:06:57.984 KVCTest[42960:903] handle error here
2010-01-08 18:06:57.984 KVCTest[42960:903] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<KVCClass 0x10010c680> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key nonexistentKey.'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00007fff851dc444 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff866fa0f3 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff85233a19 -[NSException raise] + 9
    3   Foundation                          0x00007fff85659429 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
    4   KVCTest                             0x0000000100001b78 main + 328
    5   KVCTest                             0x0000000100001a28 start + 52
    6   ???                                 0x0000000000000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Abort trap

Это показывает, что первая попытка доступа к ключу nonexistentKey была успешно перехвачена программой, вторая вызвала исключение, подобное вашей.

...