2009-08-16 40 views
164

estoy recibiendo un mensaje de error extraño de los datos básicos al intentar guardar pero el problema de que el error no es reproducible (que aparece en diferentes momentos al hacer diferentes tareas)iphone datos básicos sin resolver error al guardar

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

+0

Esto podría ayudarlo: "Manejo de errores" iPhone Core Data "" http://stackoverflow.com/questions/2262704/iphone-core-data-production-error-handling/3510918#3510918 –

Respuesta

286

Significa que hay una propiedad obligatoria asignada nil. 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 limpiando tu compilación y elimina la aplicación desde tu iPhone Simulator/dispositivo iPhone. El cambio de modelo puede entrar en conflicto con la implementación del modelo anterior.

Editar:

casi me olvido de todos los códigos de error que datos básicos escupe aquí: Core Data Constants Reference tuve problemas con esto antes y me di cuenta de que yo no se la casilla opcional correcta. Tal problema para descubrir el problema. Buena suerte.

+1

Esto lo resolvió para yo. También tenga en cuenta que, al menos en mi experiencia, aunque no se guardó en el archivo sqlite, los cambios se abrieron paso en el contexto. Entonces, el comportamiento puede ser errático cuando esto sucede. – nickthedude

+0

No pude entender la causa raíz, pero logré que el problema desapareciera al hacer que todas las propiedades fueran opcionales. –

+0

¿Ha probado el código de Charles, le diría qué campo es el problema. –

232

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 the reference docs here.

Este es el bloque de código que utilizo para obtener una salida razonable a partir del error devuelto durante un salvamento:

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]); 
     } 
    } 

Se producirá una salida que le indica los campos que están en falta, lo que hace que solucionar el problema significativamente más fácil de tratar.

+0

Muchas gracias por este código. Hace mucho más simple el seguimiento de problemas de CoreData. – MiKL

+0

Gracias, he registrado su fragmento en mi Xcode ... :) – barley

21

Estoy arrojando esto como una respuesta, a pesar de que 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 '[[[UIApplication sharedApplication] delegada] 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 encontré con el problema de el OP, apuntando directamente a las entidades de datos centrales no opcionales que había olvidado establecer antes de intentar guardar.

+0

También es muy útil. Especialmente cuando obtiene estas cadenas de descripción de entidades de datos principales \ n \ n \ n en bruto. – Lukasz

+0

aseado. 'mensaje' no se usa por cierto. – pojo

0

El problema me tocó cuando guardo el segundo registro en CoreData. Todos los campos no opcionales (relación) se rellenaron 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.

Por lo tanto, 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) 

Cambiando la relación de los padres de uno a uno a muchos a uno resuelto esta tarea.

0

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.

0

I significa que su modelo no pudo validar, lo que podría ocurrir por varias razones: propiedad no utilizada en su modelo, valor faltante marcado como requerido. para obtener una mejor comprensión de qué es exactamente lo que salió mal, poner un punto de interrupción en un lugar donde se encuentre listo para guardar el objeto y llamar a uno de los validateFor... variantes del método, 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.

Cuestiones relacionadas