假设我有一个NSManagedObject
名为的子类Item
.每当item
保存实例时,我想根据瞬态属性中的计算值更新属性.我知道只要瞬态属性发生变化,我就可以更新属性,但是对于这个问题,假设有一个很好的理由我不想这样做.
我尝试在willSave
方法中执行以下操作:
- (void)willSave { self.computedProperty = [self computedValueFromTransientProperty]; }
这会在保存上下文时导致崩溃.如果我移出代码willSave
并在调用save之前显式设置属性,它可以正常工作.apple docs说你应该避免更改托管对象属性willSave
.
问题:是否有一种很好的方法可以在NSManagedObject
子类中构建功能,因此可以在保存之前更新属性,无需在类外部显式设置属性,并且每次瞬态属性更改时都不设置属性?
你可以设置持久性属性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
将被调用两次,因此如果方法计算成本昂贵,您可能不希望这样做.
另一种选择是使用原始set方法,这意味着willSave
不会被调用两次,但可能会产生副作用,具体取决于您的应用与Core Data的交互方式:
- (void)willSave { self.primitiveComputedProperty = [self computedValueFromTransientProperty]; }