2009-08-16 14 views
164

sto ottenendo un messaggio di errore strano sulla base dei dati di base quando si cerca di salvare ma il problema che l'errore non è riproducibile (appare in momenti diversi quando si fa attività diverse)iphone Errore non risolto Core Data, mentre il risparmio

il messaggio di errore:

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.)" 
); 
} 

e il metodo che genera l'errore è:

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

qualche idea per il motivo di questo messaggio? dando che appare in modo casuale

+0

Questo potrebbe aiutarti: "Gestione dei dati di iPhone Core" Gestione degli errori "http://stackoverflow.com/questions/2262704/iphone-core-data-production-error-handling/3510918#3510918 –

risposta

286

Significa che è stata assegnata una proprietà obbligatoria a zero. Nel tuo * .xcodatamodel controlla la casella "opzionale" o quando stai salvando su managedObjectContext assicurati che le tue proprietà siano compilate.

Se ricevi ulteriori errori dopo aver modificato il tuo codice per soddisfare i due requisiti prova pulire la tua build ed eliminare l'applicazione dal tuo dispositivo iPhone Simulator/iPhone. La modifica del modello potrebbe entrare in conflitto con la vecchia implementazione del modello.

Edit:

quasi dimenticavo ecco tutti i codici di errore che Core Data sputa fuori: Core Data Constants Reference Ho avuto problemi con questo prima e ho capito che deselezionato la casella di opzione corretta. Tale problema a scoprire il problema. In bocca al lupo.

+1

Questo l'ha risolto per me. Si noti inoltre che, almeno nella mia esperienza, anche se non è stato salvato nel file sqlite, le modifiche si sono fatte strada nel contesto. Quindi il comportamento potrebbe essere irregolare quando ciò accade. – nickthedude

+0

Non sono riuscito a ottenere la causa principale, ma sono riuscito a risolvere il problema rendendo tutte le proprietà facoltative. –

+0

Hai provato il codice di Charles, ti direbbe quale campo sono il problema. –

232

Ho lottato con questo per un po 'di tempo. Il vero problema qui è che il debug che hai non ti mostra quale sia il problema. La ragione per questo è che CoreData metterà una matrice di oggetti NSError nell'oggetto NSError "top level" che restituisce se c'è più di un problema (Questo è il motivo per cui vedi l'errore 1560, che indica più problemi, e un array di errori 1570s). Sembra che CoreData abbia una manciata di chiavi che usa per immagazzinare le informazioni nell'errore restituito se c'è un problema che ti darà più informazioni utili (come l'entità su cui si è verificato l'errore, la relazione/attributo che mancava, ecc.). Le chiavi che usi per ispezionare il dizionario utente Info possono essere trovate in the reference docs here.

Questo è il blocco di codice che uso per ottenere l'uscita ragionevole dall'errore restituito durante un salvataggio:

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

Sarà produrre un output che ti dice i campi che sono mancanti, il che rende risolvere il problema significativamente più facile da gestire.

+0

Grazie mille per questo codice. Rende molto più semplice il tracciamento dei problemi con CoreData. – MiKL

+0

Grazie, ho registrato il tuo snippet sul mio Xcode ... :) – barley

21

Sto gettando questo come risposta, anche se è davvero più di un abbellimento al frammento di Charles. L'output diretto da NSLog può essere un pasticcio da leggere e interpretare, quindi mi piace buttare un po 'di spazio bianco e richiamare il valore di alcune chiavi critiche "userInfo".

Ecco una versione del metodo che ho utilizzato. ('_sharedManagedObjectContext' è un #define per '[[[UIApplication sharedApplication] delegato] 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; 
} 

Questo mi permette di vedere il valore per 'NSValidationErrorKey', che, quando ho incontrato la questione da l'OP, puntato direttamente alle entità di Core Data non opzionali che avevo dimenticato di impostare prima di provare a salvare.

+0

Molto utile. Specialmente quando ottieni queste stringhe di descrizione delle entità dei dati core \ n \ n \ n. – Lukasz

+0

Neat. 'messaggio' non è usato btw. – pojo

0

Il problema mi ha toccato quando ho salvato il secondo record su CoreData. Tutti i campi non facoltativi (relazione) sono stati compilati anche senza nullo, ma nell'output degli errori noterei che uno dei campi nel primo oggetto salvato era diventato nullo. Strano un po '? Ma la ragione è piuttosto banale: rapporto uno a uno che annulla il primo oggetto, quando lo imposto nel secondo.

Così, lo schema è:

"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) 

Cambiare il rapporto di genitore da One to One per molti a uno risolto questo compito.

0

Avevo una proprietà temporanea di tipo int che non era facoltativa. Ovviamente, quando è stato impostato su 0, appare l'errore 1570. Ho appena cambiato tutte le mie proprietà transitori in facoltativo. Se necessario, la logica di controllo nullo può essere implementata nel codice.

0

Voglio dire che il tuo modello non è riuscito a convalidare, cosa che potrebbe accadere per una serie di ragioni: proprietà inutilizzate nel tuo modello, valore mancante che è contrassegnato come richiesto. Per ottenere una migliore comprensione di ciò che esattamente è andato storto, mettere un punto di interruzione in un luogo in cui si è pronti a salvare il vostro oggetto, e chiamare uno dei validateFor... varianti di metodo, come:

po [myObject validateForInsert]

informazioni più dettagliate riguardo al problema è nella descrizione dell'errore. Convalida riuscita significa che non otterrai alcun risultato.

Problemi correlati