Restricciones exclusivas de Core Data – "Referencia de suspensión a un object no válido" al save

Estoy presentando Restricciones únicas a una aplicación existente, en una nueva versión de model.

El model tiene una entidad Persona que tiene una relación opcional de uno a uno con la entidad Pet. La regla de eliminación de la persona es cascada, y la regla de eliminación de la relación inversa de Pet se anula. Hay otra entidad, Job, cuya Persona también tiene una relación de uno a uno. Pero esa regla de eliminación, y la regla de eliminación inversa, son anuladas.

La persona tiene una propiedad "personID" que he hecho única.

En un context de queue principal, tengo una instancia de Persona, con ID xxx, que no tiene un set de Pet. Llamemos a esa persona "Charlie". También creo un trabajo y lo establezco como "iOS Dev", y lo asigno a la propiedad de trabajo de Charlie.

Luego, en un context de queue privada hijo, inserto un nuevo "Charlie" también con ID xxx (la restricción única) y creo una mascota y la configuro. No establezco un trabajo. Guardo el context secundario sin problemas.

Inmediatamente después, bash save el context de la queue principal. Pero justo antes de eso, inspecciono la propiedad insertedObjects del context de Cola Principal y veo, como espero, una instancia de Persona con ID xxx. Lo que espero es que esta segunda instancia sea manejada por restricciones únicas y se "fusione" con la instancia original de la Persona del párrafo anterior. Pero, cuando realmente llamo al método save: MOC, arroja una exception e inspecciono el object NSError:

Error de dominio = NSCocoaErrorDomain Code = 1550 "La operación no se pudo completar. (Error de cocoa 1550.)" UserInfo = {Dangling reference a un object inválido. = Null

¿Alguna idea sobre cómo evitar la exception? Estoy acostumbrado a "Dangling references" en Core Data, lo que significa que una relación está mal configurada, pero la he revisado varias veces y parece estar bien, así que no estoy seguro de qué otra cosa solucionar. Tengo implicados todos los contexts utilizando la política de combinación NSMergeByPropertyObjectTrumpMergePolicy.

Obviamente, esto es un poco difícil de seguir, así que lancé un proyecto de ejemplo sobre Github en caso de que alguien esté interesado: https://github.com/bpapa/core-data-unique-bug

Terminé de grabar un ticket de soporte de nivel de código en esto, y un ingeniero de Apple confirmó que hay un error. Como solución alternativa, se recomendó escribir mi propia política de combinación que llama súper y luego se asegura manualmente de que la relación se establece en ambos extremos.

Si desea emplear la nueva estrategia de Restricciones únicas de iOS 9, debe asegurarse de que ambos contexts tengan el mismo set de políticas de combinación .

Tenga en count que esto no lo ayudará si tiene un escenario donde la instancia más nueva del object tiene un atributo / relación nil y su intención es siempre "boost" el object, es decir, completar los attributes que faltan y actualizar los existentes.

De lo contrario, para pre-iOS9, lo siguiente es válido.

Tal vez haya algún malentendido sobre el significado de la política de fusión que emplea ( NSMergeByPropertyObjectTrumpMergePolicy ). Se refiere a una situación en la que tiene una versión de un object en la memory y otra en la tienda persistente, no dos versiones en la memory en diferentes contexts. De los files de encabezado:

Esta política singleton fusiona los conflictos entre la versión de la tienda persistente del object y la versión actual en la memory.

Por lo tanto, su process de creación de un nuevo object no es el enfoque correcto.

En su lugar, debe search la Person en el context secundario utilizando la identificación única.

Alternativamente, podría hacer que objectID la persona (un artefacto opaco de Datos del Núcleo) esté disponible para el context secundario para get una reference al mismo object en el gráfico del object usando objectWithID:

Fusionar los cambios en el context principal utilizando el guardado de notificación del context de background. Ver muestra de Manzanas Terremotos.