6

过去,我发布的应用程序带有预加载的数据库,因此用户不必在第一次运行时更新它。我在另一个关于 SO 的问题中发现了一些代码(对不起,不再有链接),我添加到我的 App Delegate 的persistentStoreCoordinator方法中:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"db.sqlite"];
    if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]])
    {
        NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"db" ofType:@"sqlite"]];
        NSError* err = nil;

        if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err])
        {
            NSLog (@"Error - Could not preload database.");
        }
    }

//... more code generated from the template here
}

当我尝试在 iOS 7 中执行此操作时,我没有收到任何错误,但数据库是空的(即使我的数据库中mainBundle有我期望的所有信息)。我注意到有更多的数据库文件(一个 .sqlite-shm 文件和一个 .sqlite-wal 文件)applicationDocumentsDirectory。我还需要对这些文件做些什么吗?还是不再可能在应用程序中提供预加载的数据库?

编辑:我尝试添加代码来复制新的 .sqlite-shm 和 .sqlite-wal 文件,但这没有帮助。

4

2 回答 2

6

我也复制了 .sqlite-shm 和 .sqlite-wal 文件,它工作正常:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite"];

// Check if the sqlite store exists
if (![[NSFileManager defaultManager] fileExistsAtPath:storePath]) {
    NSLog(@"File not found... copy from bundle");

    // copy the sqlite files to the store location.
    NSString *bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite"];
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil];

    bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite-wal"];
    storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite-wal"];
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil];

    bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite-shm"];
    storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite-shm"];
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil];
}
else {
    NSLog(@"File exists");
}

(基于:App Bundle 中包含的 Core Data Store

于 2014-05-03T11:27:10.487 回答
5

iOS 7 中的 Core Data 发生了一些变化,主要是如何执行保存。

引入预写日志 (wal) 是为了提高性能,因此您会看到 WAL sqlite 文件。

您可以告诉您的应用使用旧的“日志模式”:

您可以通过在调用 addPersistentStoreWithType:configuration:url:options:error 时将 NSSQLitePragmasOption 添加到选项来指定日志模式。例如设置以前的默认删除模式:

NSDictionary *options = @{ NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"} };

资源

我不确定这是否能解决您的问题,但这是 iOS 7 中 Core Data 发生的重大变化

如果你想了解更多关于 WAL 的信息,我建议观看WWDC session #207,“Whats New In Core Data & iCloud”

于 2013-11-14T16:21:20.660 回答