KVC: как проверить существующий ключ

Мне нужна небольшая помощь о 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"

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

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

Спасибо

Дарио


person Fulkron    schedule 17.09.2009    source источник


Ответы (1)


Хотя я не могу придумать способ узнать, какие ключи будет поддерживать объект, вы могли бы использовать тот факт, что когда вы устанавливаете значение для несуществующего ключа, поведение вашего объекта по умолчанию - генерировать исключение. Вы можете заключить вызов метода 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 была хорошо отловлена ​​программой, вторая сгенерировала исключение, похожее на ваше.

person szzsolt    schedule 08.01.2010