核心数据:发送瞬态衍生属性的KVO通知

时间:2013-05-24 15:06:16

标签: ios cocoa-touch core-data key-value-observing

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

DerivedProperty的值取决于Parent.IndependentProperty1的值,因此每当IndependentProperty1发生变化时,DerivedProperty的值都会发生变化。但是,ParentChild(称为children)之间存在多对多关系,而DerivedProperty也与所有{IndependentProperty2的值Parent有关。 1}}的{​​{1}}个对象。

因此,只要Child IndependentProperty1 ParentIndependentProperty2对象发生变化,我就会通知任何观察者Child也发生了变化

到目前为止,我已经得到了以下代码。唯一的问题是没有为DerivedProperty发出KVO通知,因为如果我尝试在DerivedProperty中执行此操作,那么代码将以循环结束。

objectContextDidChange:

我确信我需要彻底重新考虑我的做法。我已经尝试使用KVO来观察多对多关系中的- (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 ; } IndependentProperty1,但我似乎无法让它正常工作。如果派生属性不依赖于多对多关系,那么我确信我可以使用IndependentProperty2,但当然这对多对多关系无效。

如何使用依赖于多对多关系的Core Data瞬态衍生属性获取KVO通知?

1 个答案:

答案 0 :(得分:2)

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

其次,NSManagedObject的子类默认关闭自动KVO。这是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使用瞬态属性 AND 直接访问属性的iVar。这有效地创建了两个iVar,一个由Core Data维护,另一个由OP的代码维护。这导致了碰撞。

如果您使用的是瞬态属性,建议您按照建议将计算移动到另一个方法,并将访问者留给核心数据。