2014-04-15 24 views
7

Possiedo un'applicazione basata su dati di base che utilizza Dropbox per eseguire il backup e ripristinare i dati. Il modo in cui eseguo il backup è abbastanza semplice. Copio il file .sqlite nella casella personale dell'utente.Backup .sqlite (dati principali)

Ora la mia funzionalità di backup e ripristino funziona correttamente. Il problema è con il file .sqlite stesso. Sembra che il file .sqlite sia incompleto.

Ho inserito circa 125 voci nella mia applicazione e ho eseguito un backup. Il backup è apparso nella mia casella personale, ma quando uso uno strumento .sqlite explorer per vedere i contenuti, vedo solo i record fino alla 117esima voce.

Ho tentato di aggiornare la prima voce e poi di nuovo osservando il file .sqlite ma non ho più modificato.

Ciò che è ancora più strano è che l'app sembra aver registrato tutte le modifiche. Quando aggiungo una nuova voce o ne aggiorno una esistente e riavvia l'app, i dati aggiunti di recente sembrano persistere. Ma questi dati aggiunti di recente non compaiono nel mio file .sqlite.

Sto sostenendo utilizzando questo codice:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 
NSString *filePath = [[[appDelegate applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"MyApp.sqlite"]; 


if (account) { 
    if ([filesystem isShutDown]) { 
     filesystem = [[DBFilesystem alloc] initWithAccount:account]; 
     [DBFilesystem setSharedFilesystem:filesystem]; 
    } 

    DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:@"Backup - %@.sqlite", [NSDate date]]]; 
    DBFile *file = [[DBFilesystem sharedFilesystem] createFile:newPath error:nil]; 
    [file writeContentsOfFile:filePath shouldSteal:NO error:nil]; 
    [filesystem shutDown]; 

} 

Ho anche copiato il file .sqlite dalla cartella del simulatore e ha cercato di vedere nel browser .sqlite. Esibisce ancora lo stesso comportamento. Qualche ragione per cui questo deve accadere?

risposta

6

A partire da iOS 7/OS X 10.9, i dati principali utilizzano "Write-Ahead Logging" (WAL) come modalità di journaling predefinita per il file di archivio SQLite sottostante. Questo è spiegato in

Technical Q&A QA1809: New default journaling mode for Core Data SQLite stores in iOS 7 and OS X Mavericks

Con la modalità WAL, Core Data mantiene il file negozio principale intatta e aggiunge transazioni in un file -wal nella stessa posizione. Dopo che il contesto dei dati principali viene salvato, il file -wal non viene eliminato e i dati in tale file non vengono uniti al file di archivio. Pertanto, semplicemente fare copie del file di archivio causerà probabilmente la perdita di dati e l'incoerenza di .

Questo dovrebbe spiegare perché il file .sqlite da solo è incompleto. Come come soluzione che si può (spiegato anche in quello Nota tecnica):

  • Disabilita WAL-mode (e utilizzare il "vecchio" modo di rollback journaling) per l'archivio SQLite impostando il

    @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}}; 
    

    opzione quando si aggiunge il negozio persistente o

  • Usare il

    - (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error 
    

    metodo per creare una copia di backup dell'archivio dei dati principali.

+0

Quindi cosa consiglieresti? Apple consiglia il tuo secondo approccio ma non capisco come potrei usarlo con dropbox (sembra fatto su misura per iCloud). Se disattivo la modalità WAL ora, perderò i dati già inseriti?E cosa ne pensi di creare un file zip con il file .sqlite e il file wal e salvarlo come backup (e fare il reverse per ripristinare)? –

+0

@GauravWadhwani: In questa risposta http://stackoverflow.com/a/21002923/1187415 si afferma che l'apertura dello store con journal_mode = DELETE non * distrugge * i tuoi dati, ma non l'ho testato personalmente. Con il secondo approccio, è necessario prima eseguire il backup su un archivio separato (file singolo) che è possibile quindi spostare nella casella personale (ma non ho familiarità con le funzioni della casella personale). - Scusa, non posso darti dei consigli. Forse un'altra risposta arriverà e aiuterà di più. –

+0

Grazie per la risposta. Mi ha aiutato a risolvere il mio problema :) –