在iOS 7中预加载数据库
在过去,我发布的应用程序带有一个预加载的数据库,因此用户不必在第一次运行时更新它。我在上的另一个问题中发现了一些代码,因此(很抱歉,没有链接),我将其添加到我的应用程序代理的在iOS 7中预加载数据库,ios,objective-c,core-data,ios7,Ios,Objective C,Core Data,Ios7,在过去,我发布的应用程序带有一个预加载的数据库,因此用户不必在第一次运行时更新它。我在上的另一个问题中发现了一些代码,因此(很抱歉,没有链接),我将其添加到我的应用程序代理的persistentstorecordinator方法中: - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppen
persistentstorecordinator
方法中:
- (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
中的数据库包含了我期望的所有信息)。我注意到在applicationDocumentsDirectory
中有更多的数据库文件(一个.sqlite shm文件和一个.sqlite wal文件)。我也需要对这些文件做些什么吗?或者,应用程序不再可能附带预加载的数据库
编辑:我尝试添加代码来复制新的.sqlite shm和.sqlite wal文件,但没有帮助。在iOS 7中,核心数据发生了一些变化,主要是执行保存的方式 引入预写日志(wal)是为了提高性能,因此您可以看到wal sqlite文件 您可以告诉您的应用程序使用旧的“日记模式”: 可以通过添加nssqlitepragmas选项来指定日志模式 在呼叫时选择选项 addPersistentStoreWithType:配置:url:选项:错误。例如到 设置删除之前的默认模式: 我不确定这是否能解决您的问题,但iOS 7中的核心数据改变了这一点
如果您想了解更多关于WAL的信息,我建议您观看我还复制了.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");
}
(基于:)Yep,添加
options
dictionary就可以了。我将查看您链接的视频,希望这不是我最终需要的东西=)。否则,我想我必须找到另一个解决方案,但这似乎暂时有效。WAL确实提高了多线程应用程序的性能,所以在更改日志模式时要小心。不过,我不知道如何在启用WAL的情况下运送预填充的数据库。@DavidCaunt:目前我并不太关心我的应用程序的性能。在我的应用程序的前一个版本中,数据库操作相当慢,但我显著地减少了许多表以消除浪费的空间,并更改了回迁以更好地获取会话中需要的信息。在这些修改之后,几乎没有可检测的延迟。如果有什么变化,性能又开始下降,我会记住再次查看WAL-谢谢。@davidcarn:Followup-WWDC视频提到WAL样式可能无法与NSFileManager
配合使用,这是我用来进行预加载的,所以我想这是预期的行为。苹果是否会改变任何东西,使其在未来兼容可能是任何人的猜测。如果他们不这样做,看起来我们需要想出一种全新的方法让数据库与应用程序一起安装。
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");
}