核心数据:发送KVO通知,以获取瞬态派生属性

我有一个自定义类,有一个瞬态和派生(只读)属性称为DerivedProperty Parent实体。

DerivedProperty的值取决于DerivedProperty的值,因此只要IndependentProperty1发生更改, DerivedProperty的值就会改变。 但是, ParentChild (称为children )具有多对多关系,并且DerivedProperty也依赖于Parent的所有Child对象中的IndependentProperty2的值。

因此,只要Parent IndependentProperty2Child对象的IndependentProperty2发生更改,我想通知任何观察者DerivedProperty也已更改。

到目前为止,我已经到了以下代码。 唯一的问题是没有发出KVO通知为DerivedProperty因为如果我尝试在objectContextDidChange:做到这objectContextDidChange:那么代码将最终在一个循环。

 - (void) awakeFromInsert { [super awakeFromInsert]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(objectContextDidChange:) name:NSManagedObjectContextObjectsDidChangeNotification object:self.managedObjectContext]; } - (void) awakeFromFetch { [super awakeFromFetch]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(objectContextDidChange:) name:NSManagedObjectContextObjectsDidChangeNotification object:self.managedObjectContext]; } - (void) objectContextDidChange: (NSNotification *) notification { NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey]; if ([updatedObjects containsObject:self] || [updatedObjects intersectsSet:self.children]) { //clear caches _derivedProperty = nil; } } - (void) didTurnIntoFault { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (NSString *) DerivedProperty { if (_derivedProperty == nil) { _derivedProperty = [self someExpensiveCalculation]; } return _derivedProperty ; } 

我确定我需要重新思考我的方法。 我已经尝试使用KVO来观察对多的关系的IndependentProperty1IndependentProperty2 ,但我似乎无法得到它正确的工作。 如果派生属性不依赖于一对多的关系,那么我敢肯定,我可以使用keyPathsForValuesAffectingValueForKey:但当然,这不会跨越一对多的关系。

如何获得KVO通知与Core Data瞬态,依赖于多对多关系的派生属性?

首先,您在-objectContextDidChange:方法中访问DerivedProperty的ivar,并且短路KVO通知。 你应该真的在内部重新实现属性作为读/写,并使用生成器访问器。

其次, NSManagedObject子类默认情况下自动closuresKVO。 这是Core Data架构的一部分。 因此,如果您不打算使用访问者,您将希望自己触发通知:

 - (void) objectContextDidChange: (NSNotification *) notification { NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey]; if ([updatedObjects containsObject:self] || [updatedObjects intersectsSet:self.children]) { //clear caches [self willChangeValueForKey:@"derivedProperty"]; _derivedProperty = nil; [self didChangeValueForKey:@"derivedProperty"]; } } 

注意

在这种情况下,OP使用瞬态属性直接访问属性的iVar。 这有效地创build了两个iVar,一个由Core Data维护,另一个由OP的代码维护。 这是造成碰撞。

如果您正在使用瞬态属性,build议您按照build议将计算移至其他方法,并将访问者留给核心数据。