2012-04-17 27 views
6

Considere el siguiente modelo de entidad simple: La entidad A tiene una relación de uno a uno con la entidad B llamada b. La entidad B tiene una relación inversa a uno llamada a. Ninguna de las relaciones es opcional.Integridad relacional y validación en datos básicos Sincronización de iCloud

A   B 
b < ----- > a 

Supongamos que tenemos dos dispositivos (1) y (2) que comienzan totalmente sincronizado. Cada uno tiene un objeto de clase A y un objeto de clase B y están asociados entre sí. En el dispositivo 1, tenemos los objetos A1 y B1, y en el dispositivo B tenemos los mismos objetos lógicos A1 y B1.

Supongamos ahora que los cambios simulateous se realizan en cada dispositivo:

El dispositivo 1, que elimine B1, B2 insertar, y asociarse con A1 B2. Luego guarde los cambios.
En el dispositivo 2, eliminamos B1, insertamos B3 y asociamos A1 con B3. Luego guarda los cambios.

El dispositivo 1 ahora intenta importar los registros de transacciones del dispositivo 2. Se insertará B3 y A1 se asociará con B3. Hasta ahora todo bien, pero B2 ahora se queda con la relación a igual a nil. La relación a no es opcional, por lo que se produce un error de validación.

Algo similar ocurrirá en el dispositivo 2, porque hay dos objetos B y solo un objeto A con el que se asociará. Siempre debe haber un error de validación, porque uno de los objetos B debe tener una relación a establecida en nil.

Peor aún, cualquier cambio futuro siempre dejará un objeto B errante dando vueltas, y por lo tanto fallará la validación. En efecto, el usuario no puede solucionar el problema restableciendo la relación. Está permanentemente roto.

La pregunta es, ¿cómo se puede abordar un error de validación como este? Todo esto sucede antes de que se active la notificación NSPersistentStoreDidImportUbiquitousContentChangesNotification. No es un error de validación en la aplicación principal NSManagedObjectContext, es un error de validación que se produce durante la importación inicial de registros de transacciones en la tienda persistente.

La única opción que se me ocurre es quizás para tratar de eliminar el objeto B no válido en un montador de encargo (setA:), o en un método de validación KVC (validateA:error:) en la propia clase B, ya que estos parecen ser desencadenado durante la importación del registro de transacciones. Pero no estoy seguro de que los efectos secundarios como estos estén permitidos, y cuando lo intento, parece dar lugar a mensajes de registro desagradables a tal efecto.

¿Alguien sabe cuál es la forma correcta de manejar esto?

Respuesta

2

Control hacia fuera este hilo en Foros de desarrolladores de Apple:

https://devforums.apple.com/message/641930#641930

Hay una respuesta por parte de un empleado de Apple. En pocas palabras:

1) Este es un error conocido en la sincronización de Core Data iCloud con las versiones actuales de iOS (5.1) y OS X (10.7.3).

2) Si la relación no es opcional con un predicado de validación, la sincronización cesará por completo. Por lo tanto, deberá eliminar la validación por el tiempo necesario para que todo siga fluyendo. Sin embargo, al hacerlo, los dispositivos dejarán datos incompatibles.

3) No hay una solución oficial para esto. Un enfoque, que es desordenado, sería mantener un atributo separado que rastree la relación. Luego, necesitarás escanear cualquier objeto modificado a través de iCloud y arreglar la relación si es nula.

También me pica este error. Es muy frustrante lidiar con clientes que tienen problemas. Esperemos que una solución de Apple salga pronto ...

+0

Gracias, eso es muy útil. La publicación del foro de desarrollo parece indicar que esto es solo un problema para muchas relaciones, pero no creo que sea así. Surgirá en cualquier situación donde una relación requerida se modifique simultáneamente. En cualquier caso, al menos sé que esto es un error en el marco y puedo tratar de evitarlo. –

+0

¿Sigue ocurriendo este problema en 6.x y 10.8.x? –

+0

Desafortunadamente, sí, todavía existe como un problema en iOS 6.1. – thevoid

1

En caso de que esto ayude a los demás, he avanzado un poco más trabajando alrededor de este error en iCloud. Lo que hice fue la validación deshabilitada durante la importación inicial del registro de transacciones, y lo habilité nuevamente cuando mi MOC va a guardar en mi tienda principal. Todavía recibo errores de validación, por supuesto, pero ocurren en mi método de guardado de MOC, en lugar de en el marco de Core Data, por lo que puedo reparar los errores (por ejemplo, eliminar objetos no válidos).

¿Cómo 'desactivo' la validación? La forma en que lo hago es anular el método de validación de KVC en mi subclase NSManagedObject, que he utilizado como la clase raíz para todas las clases de entidades de datos básicos.

-(BOOL)validateValue:(__autoreleasing id *)value forKey:(NSString *)key error:(NSError *__autoreleasing *)error 
{ 
    if (![self.managedObjectContext isKindOfClass:[MCManagedObjectContext class]]) { 
     return YES; 
    } 
    else { 
     return [super validateValue:value forKey:key error:error]; 
    } 
} 

En la anulación, puedo comprobar la clase del contexto de objeto gestionado, y si es mi clase de aduana, hago la validación normalmente encadenando al método súper. Si no es mi subclase personalizada, devuelvo SÍ para indicar la validez.

Por supuesto, puede hacer que este sea más matizado, pero ojalá que entienda la idea: intenta determinar si este es uno de los archivos guardados estándar de su aplicación o un ahorro de importación de iCloud, y la rama en consecuencia.

Cuestiones relacionadas