1

In einer Unterklasse von NSManagedObject wird meine überschriebene Implementierung von willTurnIntoFault zweimal aufgerufen, wenn Code rückgängig gemacht wird, der das betreffende Objekt ursprünglich erstellt hat. Dies führt zu einem Absturz beim Versuch, die Registrierung für KVO auf einem Schlüsselpfad doppelt aufzuheben.willTurnIntoFault wird mehr als einmal aufgerufen, was zum Absturz führt

Die Apple-Dokumente sagen, dass dies der richtige Ort ist, um sich für KVO abzumelden.

Ein bisschen Kontext - die Rückgängig-Operation beinhaltet das Entfernen der entsprechenden Ansicht des Modells aus seiner Superansicht. Die Ansicht behält ihr Modell bei.

Also meine Frage ist: welche Art von Programmierfehlern in willTurnIntoFault dazu aufgerufen, zweimal in einer Unterklasse von NSManagedObject führen kann?

Hinweis: Zuvor hatte ich in dieser Klasse dealloc überschrieben, habe aber inzwischen erkannt, dass dies für Unterklassen von NSManagedObject nicht empfohlen wird. Ich habe seitdem diesen Code in -didTurnIntoFault verschoben. Ich übergehe derzeit keine anderen Methoden, die laut Apple-Dokument nicht überschrieben werden sollten.

Antwort

0

Scheint, dass das Problem durch eine benutzerdefinierte Setter-Methode verursacht wurde, die KVO-Werte innerhalb von willTurnIntoFault gesetzt/unscharf geschaltet hat.

3

Für die Nachwelt: Ich hatte das gleiche Problem. In meinem Fall hatte ich ein Objekt A mit einer (zu einer) Beziehung zu einem Objekt B. Wenn A bekam B ‚s inverse Beziehung zu gelöscht A auf null gesetzt wurde. Dies verursacht B 's observeValueOfKeyPath:ofObject:change:context Methode aufgerufen werden soll (wobei keypath war B' s bezogen auf A). Leider hat diese Methode eine Eigenschaft von A überprüft, wodurch der Fehler von A abgebrochen wird (beachten Sie, dass in dieser Situation awakeFromFetch nicht aufgerufen wird - ich nehme an, da das Objekt nie tatsächlich Fehlerstatus erhalten hat). Daher könnte ich später einen zweiten Anruf an willTurnIntoFault bekommen und das Objekt würde versuchen, die Registrierung für KVO wieder aufzuheben, was zu einem Absturz führt - genau wie im OP.

Für mich war die Lösung, um die Löschregel für A Kaskade zu ändern, so dass das B-Objekt gelöscht wurde, wenn das A-Objekt UND gelöscht wurde in prepareForDeletion für KVO deregistrieren. Dies ist wichtig, weil das Löschen von A immer noch B 's inverse Beziehung auf Null gesetzt wird, bevor B tatsächlich gelöscht wird.

Beachten Sie, dass prepareForDeletion vor aufgerufen wird, aber nicht anstelle vonwillTurnIntoFault. Wenn Sie die Registrierung für KVO in beiden Fällen aufheben, müssen Sie daher einen Status beibehalten, um sicherzustellen, dass Sie die Registrierung nicht bereits aufgehoben haben.

+0

Gute Beobachtung (wenn auch von der Schule der harten Schläge). –

Verwandte Themen