如何在保存之前自动设置计算的NSManagedObject属性?

时间:2011-11-18 01:37:16

标签: ios core-data nsmanagedobject

假设我有一个名为NSManagedObject的{​​{1}}子类。每当保存Item实例时,我想根据瞬态属性中的计算值更新属性。我知道我可以在瞬态属性发生变化时更新属性,但是对于这个问题,假设我有一个很好的理由不想这样做。

我尝试在item方法中执行此操作,如下所示:

willSave

这会在保存上下文时导致崩溃。如果我将代码移出- (void)willSave { self.computedProperty = [self computedValueFromTransientProperty]; } 并在调用save之前显式设置属性,则可以正常工作。 apple docs说你应该避免在willSave中更改托管对象属性。

问题:有没有一种很好的方法可以在willSave子类中构建功能,因此可以在保存之前更新属性,无需从类外部显式设置属性并且无需设置属性每次瞬态属性改变?

1 个答案:

答案 0 :(得分:7)

您可以从willSave设置持久属性,您只需要更加小心。

来自willSave文档:

  

此方法可能对持久值产生“副作用”。您可以使用   例如,它可以从其他瞬态或计算来计算持久值   暂存值。

     

如果要更新持久属性值,则应该   通常测试任何新值与现有值的相等性   在做出改变之前。如果使用标准更改属性值   访问器方法,Core Data将观察结果的变化   通知,因此在保存对象之前再次调用willSave   托管对象上下文。如果继续修改willSave中的值,   willSave将继续被调用,直到您的程序崩溃。

所以,正在发生的事情是你正在改变computedProperty,这会导致再次调用willSave,这会更改computedProperty再次调用willSave,直到你的程序崩溃。

要解决此问题,您需要检查是否需要再次设置computedProperty

- (void)willSave
{
    id computed = [self computedValueFromTransientProperty];
    if (![self.computedProperty isEqual:computed])
    {
        self.computedProperty = computed;
    }
}

这意味着computedValueFromTransientProperty将被调用两次,因此如果该方法的计算成本很高,您可能不希望这样做。

另一种选择是使用原始集合方法,这意味着willSave不会被调用两次,但可能会产生副作用,具体取决于您的应用与核心数据的交互方式:

- (void)willSave
{
    self.primitiveComputedProperty = [self computedValueFromTransientProperty];
}