核心数据:发送KVO通知,以获取瞬态派生属性
我有一个自定义类,有一个瞬态和派生(只读)属性称为DerivedProperty
Parent
实体。
DerivedProperty
的值取决于DerivedProperty
的值,因此只要IndependentProperty1
发生更改, DerivedProperty
的值就会改变。 但是, Parent
与Child
(称为children
)具有多对多关系,并且DerivedProperty
也依赖于Parent
的所有Child
对象中的IndependentProperty2
的值。
因此,只要Parent
IndependentProperty2
或Child
对象的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来观察对多的关系的IndependentProperty1
和IndependentProperty2
,但我似乎无法得到它正确的工作。 如果派生属性不依赖于一对多的关系,那么我敢肯定,我可以使用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议将计算移至其他方法,并将访问者留给核心数据。