2008-09-24 3 views
11

Apple documentation on -setPrimitiveValue:forKey: нечетко признается в двух отношениях, когда используется для управления многими отношениями.setPrimitiveValue: forKey: and to many many

Во-первых, они заявляют:

Если вы пытаетесь установить отношения ко многим новому объекту NSMutableSet, он будет (в конечном счете) терпят неудачу.

В конце концов ?! Что это значит? Неудачно ли это произойдет в течение -[NSManagedObjectContext save:]? Когда управляемый объект превращается в неисправность, а затем возвращается обратно? Когда? Могу ли я написать тестовый пример для последовательного воссоздания отказа по требованию?

Во-вторых, предоставляя образец кода, чтобы правильно обрабатывать этот случай, они пишут:

первым получить существующий набор, используя primitiveValueForKey: (обеспечить метод не возвращает nil)

Что я должен делать если/когда метод делает return 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"]; 
    } 
} 

является то, что не так?

ответ

6

Просто измените возвращаемое значение -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, вам не нужно беспокоиться об этом; Вы можете использовать Ядро данных встроенной поддержки свойств вместо:

#import <CoreData/CoreData.h> 

@interface Folder : NSManagedObject 
@property (readwrite, retain) NSSet *children; 
@end 

@implementation Folder 
@dynamic children; 
@end 

основных данные будут генерировать не только геттер/сеттер пару для children собственности, но изменяемые посаженных аксессоров, а также, так что вы можете использовать -mutableSetValueForKey: на нем и манипулировать результатом с минимальными накладными расходами.