2013-05-27 18 views
6

Alcuni clienti di un'applicazione iOS basata su Core Data riportano che occasionalmente perdono dati. Le relazioni sono molto strane, motivo per cui vorrei chiedere la tua opinione su questo. I clienti segnalano che quando riaprono l'applicazione dopo un po 'di tempo (minuti, ore o giorno successivo), alcuni dei loro dati vengono persi come se il database sottostante ripristinato a uno stato precedente.Core Data torna allo stato precedente senza motivo apparente

Ho lavorato con Core Data per diversi anni e non ho mai eseguito in un problema come questo prima. L'applicazione è abbastanza semplice, il che significa che utilizzo solo un contesto oggetto gestito e le modifiche vengono confermate prima che l'applicazione passi in secondo piano.

Mi rendo conto che questo è un campo lungo, ma quali potrebbero essere alcune potenziali cause di questo tipo di problema o quali controlli posso fare per raccogliere ulteriori informazioni? Sfortunatamente, non riesco a riprodurre il problema da solo, il che renderebbe tutto molto più semplice.

Aggiornamento:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (_persistentStoreCoordinator) return _persistentStoreCoordinator; 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Prime.sqlite"]; 

    NSError *error = nil; 
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES } error:&error]) { 
     // Error Handling 
    } 

    return _persistentStoreCoordinator; 
} 
+0

hai impostare tutte le opzioni [ 'pragma'] (http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/Articles/cdPersistentStores.html#//apple_ref/ doc/uid/TP40002875-SW12) nel tuo negozio? –

+0

@DanShelly No. Ho aggiornato la domanda con lo snippet di codice a cui ti riferisci. –

+1

Quando ** esattamente ** salvate le modifiche? –

risposta

2

Verificare se è stato inserito il messaggio di salvataggio nell'app appropriataDelegare i metodi in modo che non vi sia un modo per ripristinare l'applicazione senza salvare. applicationWillResignActive e applicationWillTerminate dovrebbero coprire tutte le vostre esigenze.

A parte questo, la corretta gestione degli errori e la registrazione dovrebbero farti guadagnare molto terreno. Mi piace personalmente registrare questi tipi di errori in un file che può essere inviato a me su richiesta. Ma potrebbe essere eccessivo per la tua particolare applicazione. Questo è scritto dalla memoria, quindi perdona ogni errore.

NSError *error = nil; 
if (![[self managedObjectContext] save:&error]) 
{ 
    NSString *errorString = @"%@ ERROR : %@ %@", [[NSDate date] description], [error localizedDescription], [error userInfo]); 

    NSString *documentsDirectory = [NSHomeDirectory() 
            stringByAppendingPathComponent:@"Documents"]; 

    NSString *filePath = [documentsDirectory 
          stringByAppendingPathComponent:@"errorLog.txt"]; 

    // Write to the file 
    [errorString writeToFile:filePath atomically:YES 
      encoding:NSUTF8StringEncoding error:&error]; 
} 
1

si dovrebbe verificare se save: metodo segnala alcun errore, per esempio come questo:

NSError *error = nil; 
if (![[self managedObjectContext] save:&error]) 
{ 
    NSLog(@"Error %@", action, [error localizedDescription]);  
    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey]; 
    // if there is a detailed errors - we can dump all of them 
    if(detailedErrors != nil && [detailedErrors count] > 0) { 
     for(NSError* detailedError in detailedErrors) { 
      NSLog(@" DetailedError: %@", [detailedError localizedDescription]); 
     } 
    } 
    else { // in other case lets dump all the info we have about the error 
     NSLog(@" %@", [error userInfo]); 
    } 
} 

Uno dei più comuni cause di errore è errore di convalida, ad esempio , potrebbe aspettarsi che un campo venga presentato mentre l'utente non lo ha inserito o potrebbe aspettarsi che il valore sia inferiore a XX caratteri e così via.

Fondamentalmente ciò significa che se ci vuole troppo tempo per fornire al client una nuova build con informazioni di debug, è possibile chiedere loro di inviarti esempi di dati che usano per entrare.

1

Non posso essere sicuro che questo sia il motivo, ma potrebbe essere che quando l'app va in secondo piano, per qualche motivo a volte viene superato il tempo massimo consentito per gestirlo (backgroundTimeRemaining). Da documenti Apple:

Questa proprietà contiene la quantità di tempo in cui l'applicazione deve essere eseguita in background prima che possa essere forzatamente uccisa dal sistema. Mentre l'applicazione è in esecuzione in primo piano, il valore in questa proprietà rimane adeguatamente grande. Se l'applicazione avvia una o più attività a esecuzione prolungata utilizzando il metodo beginBackgroundTaskWithExpirationHandler: e quindi le transizioni sullo sfondo, il valore di questa proprietà viene regolato in modo da riflettere il tempo di esecuzione dell'applicazione.

Se l'app viene uccisa perché il salvataggio del contesto richiede troppo tempo, i dati di base possono decidere di ripristinare lo stato precedente per ottenere almeno qualcosa di coerente. Se è possibile ottenere i risultati del registro da alcuni utenti che segnalano questo problema, provare a registrare il valore della proprietà dopo aver provato a salvare il contesto, per verificarlo.

+0

Come accennato nella domanda, il contesto dell'oggetto gestito viene salvato ogni volta che viene creata una nuova entità, quindi sono abbastanza certo che questa non è la causa del problema. Grazie per la tua risposta. –

Problemi correlati