willTurnIntoFault 被多次调用,导致崩溃
在 NSManagedObject 的子类中,当撤消最初创建相关对象的某些代码时,我重写的 willTurnIntoFault 实现被调用两次。当尝试在关键路径上双重注销 KVO 时,这会导致崩溃。
苹果文件称,这是取消注册 KVO 的正确位置。
一些上下文 - 撤消操作涉及从其超级视图中删除模型的相应视图。该视图保留其模型。
所以我的问题是:什么样的程序员错误会导致willTurnIntoFault
在NSManagedObject
的子类中被调用两次?
注意:以前我是覆盖的在此类中进行dealloc,但后来意识到不建议将其用于 NSManagedObject 的子类。我已将此代码移至 -didTurnIntoFault
中。我目前没有覆盖 Apple 文档说您不应覆盖的任何其他方法。
In a subclass of NSManagedObject
my overridden implementation of willTurnIntoFault
is being called twice when undoing some code which originally created the object in question. This results in a crash when attempting to double-unregister for KVO on a key path.
The Apple documents say this is the right place to un-register for KVO.
A bit of context - the undo operation involves removing the corresponding view of the model from it's superview. The view retains it's model.
So my question is: what kind of programmer errors can result in willTurnIntoFault
being called twice in a subclass of NSManagedObject
?
Note: Previously I was overriding dealloc
in this class but have since realised this is not recommended for subclasses of NSManagedObject. I've since moved this code into -didTurnIntoFault
. I'm not currently overriding any other methods which the Apple docs say you should not override.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了后代:我也遇到了同样的问题。就我而言,我有一个对象 A 与对象 B 具有(一对一)关系。当A被删除时,B与A的逆关系被设置为
null
。这导致B的observeValueOfKeyPath:ofObject:change:context
方法被调用(其中keypath
是B' s 与A的关系)。不幸的是,这个方法检查了 A 的属性,导致 A 的错误被取消(请注意,在这种情况下awakeFromFetch
不会被调用 - -我推测是因为该对象实际上从未进入故障状态)。因此,我可能会在稍后再次调用willTurnIntoFault
,并且该对象会再次尝试注销 KVO,从而导致崩溃 - 就像在 OP 中一样。对我来说,解决方案是将 A 的删除规则更改为级联,以便当 A 对象被删除AND以在
prepareForDeletion
中取消注册 KVO 时,B 对象也会被删除。这很重要,因为在实际删除 B 之前,删除 A 仍会导致 B 的逆关系设置为 nil。请注意,
prepareForDeletion
在 willTurnIntoFault 之前调用,而不是代替。因此,如果您在两者中取消注册 KVO,则需要维护某种状态以确保您尚未取消注册。For posterity's sake: I had the same problem. In my case I had an object A with a (to-one) relation to an object B. When A got deleted B's inverse relation to A was set to
null
. This caused B'sobserveValueOfKeyPath:ofObject:change:context
method to be invoked (wherekeypath
was B's relation to A). Unfortunately this method checked a property of A, causing the faulting of A to be cancelled (note that in this situationawakeFromFetch
does not get called--I presume because the object never actually did get to fault state). Hence I might might get a second call towillTurnIntoFault
later and the object would try to unregister for KVO again, resulting in a crash--just like in the OP.For me the solution was to change the delete rule for A to cascade, so that the B object got deleted when the A object got deleted AND to unregister for KVO in
prepareForDeletion
. This is important because the deletion of A will still cause B's inverse relation to be set to nil before B is actually deleted.Note that
prepareForDeletion
gets called before but not instead ofwillTurnIntoFault
. Hence, if you unregister for KVO in both, you need to maintain some state to make sure you have not already unregistered.似乎问题是由自定义 setter 方法引起的,该方法在 willTurnIntoFault 中设置/取消设置 KVO 值。
Seems the issue was caused by a custom setter method which was setting/unsetting KVO values from within willTurnIntoFault.