假设我有一个名为NSManagedObject
的{{1}}子类。每当保存Item
实例时,我想根据瞬态属性中的计算值更新属性。我知道我可以在瞬态属性发生变化时更新属性,但是对于这个问题,假设我有一个很好的理由不想这样做。
我尝试在item
方法中执行此操作,如下所示:
willSave
这会在保存上下文时导致崩溃。如果我将代码移出- (void)willSave
{
self.computedProperty = [self computedValueFromTransientProperty];
}
并在调用save之前显式设置属性,则可以正常工作。 apple docs说你应该避免在willSave
中更改托管对象属性。
问题:有没有一种很好的方法可以在willSave
子类中构建功能,因此可以在保存之前更新属性,无需从类外部显式设置属性并且无需设置属性每次瞬态属性改变?
答案 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];
}