我有一个带有自定义类的 Parent
实体,该类具有名为 DerivedProperty
的 transient 派生(只读)属性。
DerivedProperty
的值取决于 Parent.IndependentProperty1
的值,因此每当 IndependentProperty1
发生更改时,DerivedProperty 的值
将会改变。但是,Parent
与 Child
具有一对多关系(称为 children
),并且 DerivedProperty
也依赖于所有 Parent
的 Child
对象中 IndependentProperty2
的值。
因此,每当 Parent
的 IndependentProperty1
或任何 Child
对象的 IndependentProperty2
发生变化时,我想通知所有观察者 DerivedProperty
也已更改。
到目前为止我已经得到了以下代码。唯一的问题是 DerivedProperty
不会发出 KVO 通知,因为如果我尝试在 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:
但当然这不适用于一对多关系。
如何获取与依赖于一对多关系的核心数据 transient 派生属性一起使用的 KVO 通知?
最佳答案
首先,您将在 -objectContextDidChange:
方法中访问 DerivedProperty
的 ivar,并短路 KVO 通知。您确实应该在内部将属性重新实现为读/写并使用生成器访问器。
其次,NSManagedObject
的子类默认关闭自动 KVO。这是核心数据架构的一部分。因此,如果您不打算使用访问器,您可能需要自己触发通知:
- (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 使用 transient 属性并且直接访问该属性的 iVar。这有效地创建了两个 iVar,一个由 Core Data 维护,另一个由 OP 代码维护。这导致了碰撞。
如果您使用 transient 属性,建议您按照建议将计算移至其他方法,并将访问器保留为 Core Data。
关于ios - 核心数据 : Emitting KVO notifications for transient, 派生属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16738126/