备份.sqlite(核心数据)

Gau*_*ani 7 database sqlite core-data objective-c ios

我有一个基于核心数据的应用程序,它使用Dropbox备份和恢复数据.我备份的方式非常简单.我复制用户的保管箱上的.sqlite文件.

现在我的备份和恢复功能正常.问题出在.sqlite文件本身.看来.sqlite文件不完整.

我在我的应用程序中输入了大约125个条目并进行了备份.备份出现在我的Dropbox中但是当我使用.sqlite资源管理器工具查看内容时,我只看到第117个记录的记录.

我尝试更新第一个条目,然后再次观察.sqlite文件,但没有再次更改.

更奇怪的是该应用程序似乎记录了所有更改.当我添加新条目或更新现有条目并重新启动应用程序时,新添加的数据似乎仍然存在.但是这个新添加的数据不会出现在我的.sqlite文件中.

我正在使用此代码备份:

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

}
Run Code Online (Sandbox Code Playgroud)

我还从Simulator的文件夹中复制了.sqlite文件,并尝试在.sqlite浏览器中查看它.它仍然表现出相同的行为.有必要发生这种情况的原因吗?

Mar*_*n R 6

从iOS 7/OS X 10.9开始,Core Data使用"预写日志记录"(WAL)作为底层SQLite存储文件的默认日记模式.这在解释中

技术问答QA1809:iOS 7和OS X Mavericks中Core Data SQLite存储的新默认日记模式

使用WAL模式,Core Data保持主存储文件不变,并将事务附加到同一位置的-wal文件中.保存Core Data上下文后,不会删除-wal文件,并且该文件中的数据也不会合并到存储文件中.因此,简单地制作商店文件的副本可能会导致数据丢失和不一致.

这应该可以解释为什么单独的.sqlite文件不完整.作为解决方案,您可以(也在技术说明中解释):

  • 通过设置,为SQLite存储禁用WAL模式(并使用"旧"回滚日记模式)

    @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
    
    Run Code Online (Sandbox Code Playgroud)

    添加持久存储时的选项,或

  • 使用

    - (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error
    
    Run Code Online (Sandbox Code Playgroud)

    制作Core Data存储的备份副本的方法.