2009-09-17 4 views
2

Мне нужна небольшая помощь в KVC.KVC: как проверить существующий ключ

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

1) iPhone подключается (клиент) к WebService, чтобы получить объект,

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» не является ключом va lue для кодирования для ключа «myNewKey»

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

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

Благодаря

Дарио

ответ

3

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

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

Смежные вопросы