setPrimitiveValue:forKey:和一对多关系

时间:2020-03-06 14:40:48  来源:igfitidea点击:

当使用Apple来管理多对多关系时,Apple关于-setPrimitiveValue:forKey:的文档含糊不清。

首先,他们说:

If you try to set a to-many relationship to a new NSMutableSet object, it will (eventually) fail.

最终?!那有什么意思?以后会在-[NSManagedObjectContext save:]期间失败吗?当管理对象变成故障然后分页回去时?什么时候?我可以编写一个测试用例来按需一致地重新创建故障吗?

其次,提供示例代码以正确处理这种情况,他们写道:

first get the existing set using primitiveValueForKey: (ensure the method does not return 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"];
    }
}

那是错的吗?

解决方案

只需将-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];
}

如果我们可以瞄准豹子,则不必为此担心。我们可以改为使用Core Data的内置属性支持:

#import <CoreData/CoreData.h>

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

@implementation Folder
@dynamic children;
@end

核心数据不仅会为children属性生成一个getter / setter对,而且还会为该可变集合访问器生成,因此我们可以在其上使用-mutableSetValueForKey:并以最小的开销操作结果。