iphone Core Data Error no resuelto al guardar

Recibo un extraño mensaje de error de los datos centrales al intentar guardar, pero el problema es que el error no es reproducible (aparece en momentos diferentes cuando se realizan tareas diferentes)

el mensaje de error:

Unresolved error Domain=NSCocoaErrorDomain Code=1560 UserInfo=0x14f5480 "Operation could not be completed. (Cocoa error 1560.)", { NSDetailedErrors = ( Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x5406d70 "Operation could not be completed. (Cocoa error 1570.)", Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x14f9be0 "Operation could not be completed. (Cocoa error 1570.)" ); } 

y el método que genera el error es:

 - (IBAction)saveAction:(id)sender { NSError *error; if (![[self managedObjectContext] save:&error]) { // Handle error NSLog(@"Unresolved error %@, %@, %@", error, [error userInfo],[error localizedDescription]); exit(-1); // Fail } } 

alguna idea por la razón de este mensaje? dando que aparece en momentos aleatorios

Significa que hay una propiedad obligatoria asignada nula. Ya sea en su * .xcodatamodel, marque la casilla “opcional” o cuando esté guardando en managedObjectContext, asegúrese de que sus propiedades estén completas.

Si obtiene más errores después de cambiar su código para cumplir con los dos requisitos, intente limpiar su comstackción y elimine la aplicación de su iPhone Simulator / iPhone. El cambio de modelo puede entrar en conflicto con la implementación del modelo anterior.

Editar:

Casi me olvido de que aquí están todos los códigos de error que arroja Core Data: Referencia de las constantes de datos centrales Tuve problemas con esto antes y me di cuenta de que desactivé la casilla opcional correcta. Tal problema para descubrir el problema. Buena suerte.

Luché con esto por un tiempo yo mismo. El verdadero problema aquí es que la depuración que tienes no te muestra cuál es el problema. La razón de esto es porque CoreData pondrá una matriz de objetos NSError en el objeto NSError de “nivel superior” que devuelve si hay más de un problema (Es por eso que ve el error 1560, que indica múltiples problemas, y una matriz de error 1570s). Parece que CoreData tiene un puñado de claves que utiliza para esconder información en el error que devuelve si hay un problema que le dará más información útil (como la entidad en la que ocurrió el error, la relación / atributo que faltaba, etc. ) Las claves que utiliza para inspeccionar el diccionario userInfo se pueden encontrar en los documentos de referencia aquí .

Este es el bloque de código que uso para obtener un resultado razonable del error que se devuelve durante un guardado:

  NSError* error; if(![[survey managedObjectContext] save:&error]) { NSLog(@"Failed to save to data store: %@", [error localizedDescription]); NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey]; if(detailedErrors != nil && [detailedErrors count] > 0) { for(NSError* detailedError in detailedErrors) { NSLog(@" DetailedError: %@", [detailedError userInfo]); } } else { NSLog(@" %@", [error userInfo]); } } 

Producirá resultados que le indican los campos que faltan, lo que hace que sea mucho más fácil solucionar el problema.

Estoy arrojando esto como una respuesta, a pesar de que en realidad es más un embellecimiento del fragmento de Charles. La salida directa de NSLog puede ser un caos para leer e interpretar, por lo que me gustaría incluir algo de espacio en blanco y llamar el valor de algunas claves críticas de ‘userinfo’.

Aquí hay una versión del método que he estado usando. (‘_sharedManagedObjectContext’ es un #define para el delegado ‘[[[UIApplication sharedApplication]] managedObjectContext]’.)

 - (BOOL)saveData { NSError *error; if (![_sharedManagedObjectContext save:&error]) { // If Cocoa generated the error... if ([[error domain] isEqualToString:@"NSCocoaErrorDomain"]) { // ...check whether there's an NSDetailedErrors array NSDictionary *userInfo = [error userInfo]; if ([userInfo valueForKey:@"NSDetailedErrors"] != nil) { // ...and loop through the array, if so. NSArray *errors = [userInfo valueForKey:@"NSDetailedErrors"]; for (NSError *anError in errors) { NSDictionary *subUserInfo = [anError userInfo]; subUserInfo = [anError userInfo]; // Granted, this indents the NSValidation keys rather a lot // ...but it's a small loss to keep the code more readable. NSLog(@"Core Data Save Error\n\n \ NSValidationErrorKey\n%@\n\n \ NSValidationErrorPredicate\n%@\n\n \ NSValidationErrorObject\n%@\n\n \ NSLocalizedDescription\n%@", [subUserInfo valueForKey:@"NSValidationErrorKey"], [subUserInfo valueForKey:@"NSValidationErrorPredicate"], [subUserInfo valueForKey:@"NSValidationErrorObject"], [subUserInfo valueForKey:@"NSLocalizedDescription"]); } } // If there was no NSDetailedErrors array, print values directly // from the top-level userInfo object. (Hint: all of these keys // will have null values when you've got multiple errors sitting // behind the NSDetailedErrors key. else { NSLog(@"Core Data Save Error\n\n \ NSValidationErrorKey\n%@\n\n \ NSValidationErrorPredicate\n%@\n\n \ NSValidationErrorObject\n%@\n\n \ NSLocalizedDescription\n%@", [userInfo valueForKey:@"NSValidationErrorKey"], [userInfo valueForKey:@"NSValidationErrorPredicate"], [userInfo valueForKey:@"NSValidationErrorObject"], [userInfo valueForKey:@"NSLocalizedDescription"]); } } // Handle mine--or 3rd party-generated--errors else { NSLog(@"Custom Error: %@", [error localizedDescription]); } return NO; } return YES; } 

Esto me permite ver el valor de ‘NSValidationErrorKey’, que, cuando me topé con el problema del OP, apunté directamente a las entidades de datos centrales no opcionales que había olvidado establecer antes de intentar guardarlas.

El problema me tocó, cuando guardo el segundo registro en CoreData. Todos los campos no opcionales (relación) se llenaron sin nulo también, pero en la salida del error me percataría, que uno de los campos en el primer objeto guardado se había vuelto nulo. ¿Extraño un poco? Pero la razón es bastante trivial: relación de uno a uno que anula el primer objeto, cuando lo configuro en el segundo.

Entonces, el esquema es:

 "Parent" with relationship "child" One to One Create Child 1, set parent. Save - OK Create Child 2, set parent. Save - Error, Child 1.Parent == nil (behind the scene child 2 did nullify child 1 parent) 

Cambiar la relación en Parent from One to One to Many to One resolvió esta tarea.

Tenía propiedad transitoria de tipo int que no era opcional. Obviamente, cuando se configuró en 0, aparece el error 1570. Simplemente cambié todas mis propiedades transitorias a opcional. La lógica de nil check se puede implementar en el código si es necesario.

Me refiero a que su modelo no pudo validar, lo que podría suceder por varias razones: propiedad no utilizada en su modelo, valor faltante marcado como requerido. Para obtener una mejor comprensión de qué fue exactamente lo que falló, coloque un punto de interrupción en un lugar donde esté listo para guardar su objeto y llame a una de las variantes del método validateFor... como:

po [myObject validateForInsert]

Información más detallada sobre el problema está en la descripción del error. La validación exitosa significa que no obtendrá ningún resultado.