SetPrimitiveValue: отношения forKey: и to-many
Apple документация по -setPrimitiveValue:forKey:
является неопределенной двумя способами, когда используется для управления отношениями "многие-многие".
Сначала они заявляют:
Если вы попытаетесь установить отношение "ко многим" к новому объекту NSMutableSet, он (в конце концов) потерпит неудачу.
В конце концов?! Что это значит? Повредет ли он позже во время -[NSManagedObjectContext save:]
? Когда управляемый объект превращается в неисправность, а затем возвращается обратно? Когда? Могу ли я написать тестовый пример для последовательного воссоздания отказа по требованию?
Во-вторых, предоставляя пример кода для правильной обработки этого случая, они пишут:
сначала получите существующий набор, используя primitiveValueForKey:
(убедитесь, что метод не возвращает nil
)
Что делать, если/когда метод возвращает nil? assert()
он и немедленно сбой, потому что это означает, что весь граф объекта поврежден и сохранение приведет к потере данных? NSAssert()
на нем как предупреждение вызывающему, но нажмите (тихо ничего не делать)?
Прямо сейчас я просто прямо назначаю свой желаемый NS[Mutable]Set
в этом случае, например:
- (void)setChildren:(NSSet*)value_ {
NSMutableSet *mutableRelationshipSet = [[[self primitiveValueForKey:@"children"] mutableCopy] autorelease];
if (mutableRelationshipSet) {
[mutableRelationshipSet setSet:value_];
[self setPrimitiveValue:mutableRelationshipSet forKey:@"children"];
} else {
[self setPrimitiveValue:value_ forKey:@"children"];
}
}
Это неправильно?
Ответы
Ответ 1
Просто измените возвращаемое значение -primitiveValueForKey:
как изменяемый набор, полагая, что его возвращаемое значение будет правильным.
Обязательно используйте -willChangeValueForKey:withSetMutation:usingObjects:
и -didChangeValueForKey:withSetMutation:usingObjects:
вокруг своих манипуляций; вы не указали это в своем предыдущем коде.
- (void)setChildren:(NSSet *)value {
[self willChangeValueForKey:@"children" withSetMutation:NSKeyValueSetSetMutation usingObjects:value];
NSMutableSet *primitiveValue = [self primitiveValueForKey:@"children"];
[primitiveValue setSet:value];
[self didChangeValueForKey:@"children" withSetMutation:NSKeyValueSetSetMutation usingObjects:value];
}
Если вы можете нацелить Leopard, вам не нужно беспокоиться об этом; вы можете использовать встроенную поддержку свойств Core Data:
#import <CoreData/CoreData.h>
@interface Folder : NSManagedObject
@property (readwrite, retain) NSSet *children;
@end
@implementation Folder
@dynamic children;
@end
Core Data генерирует не только пару getter/setter для свойства children
, но также и аксессуры с изменяемым набором, поэтому вы можете использовать -mutableSetValueForKey:
на нем и управлять результатом с минимальными накладными расходами.