Почему setValue не установлен: forKeyPath вызывается в изменяемом исключении словаря throw для неизвестных ключевых путей?

У меня есть следующий код:

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[defs setObject:[NSNumber numberWithInt:100] forKey:@"test1.test2.test3"];
[defs setValue:[NSNumber numberWithInt:10] forKeyPath:@"test2.test3.test4"];

Я понимаю, что setObject:forKey: создает связь между ключом test1.test2.test3 и заданным номером. С другой стороны, setValue:forKeyPath: - метод Key-Value-Coding, который пытается найти объект для пути "test2.test3.test4", но в конце он просто ничего не делает. Он даже не модифицирует словарь!

Что меня смущает, так это то, что setValue:forKeyPath: не вызывает каких-либо исключений и не сообщает о какой-либо ошибке. Почему это? Является ли это поведение документированным где угодно?

Ответ 1

Я не могу найти документацию для этого конкретного случая, извините, но я предполагаю, что это:

[defs setValue:x forKeyPath:@"a.b.c"];

Выполняется примерно так:

[[defs objectForKey:@"a"] setValue:x forKeyPath:@"b.c"];

Итак objectForKey: возвращает nil, а методы, вызываемые в nil, ничего не делают. Это объясняет поведение, которое вы описали.

Ответ 2

NSMutableDictionary *dict = [@{@"test1" : [@{@"test2":[@{} mutableCopy]} mutableCopy]} mutableCopy];

[dict setValue:@(100) forKeyPath:@"test1.test2.test3"]; // ok
[dict setValue:@(200) forKeyPath:@"test1.test2.test4"]; // ok
[dict setValue:@(300) forKeyPath:@"test1.test21"];      // ok
[dict setValue:@(400) forKeyPath:@"test1.test22.test3"]; // fail, test22 not mutable

[dict setValue:[@{} mutableCopy] forKeyPath:@"test1.test23"]; // ok
[dict setValue:@(500) forKeyPath:@"test1.test23.test34"]; // ok