我在我的应用程序中使用位于MainBundle的只读sqlite数据库。在PersistentStoreCoordinator中,我使用以下代码加载数据库:
NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES]};
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self applicationManagedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[[NSBundle mainBundle] URLForResource:@"applications" withExtension:@"sqlite"] options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error description]);
abort();
}
在iOS7中,此代码在模拟器和设备中崩溃,并出现以下错误:
CoreData: error: (14) I/O error for database at /var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/applications.sqlite. SQLite error code:14, 'unable to open database file'
2014-03-22 20:45:34.346 GfxHotkeys3[1369:60b] CoreData: error: Encountered exception I/O error for database at /var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/applications.sqlite. SQLite error code:14, 'unable to open database file' with userInfo {
NSFilePath = "/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/applications.sqlite";
NSSQLiteErrorDomain = 14;
} while checking table name from store: <NSSQLiteConnection: 0x155b0fd0>
2014-03-22 20:45:34.372 GfxHotkeys3[1369:60b] Unresolved error Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x155b01b0 {NSUnderlyingException=I/O error for database at /var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/applications.sqlite. SQLite error code:14, 'unable to open database file', NSSQLiteErrorDomain=14}, Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x155b01b0 {NSUnderlyingException=I/O error for database at /var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/GfxHotkeys3.app/applications.sqlite. SQLite error code:14, 'unable to open database file', NSSQLiteErrorDomain=14}
在商店选项中传递nil,将在模拟器中运行应用程序但不在设备上运行(因为它无法在MainBundle上写入)。
我可以通过将数据库复制到文档并从那里加载来解决这个问题,但我想知道为什么会发生这种情况。我现在使用这个选项多年来从MainBundle加载只读sqlite,但是在iOS 7中崩溃......
任何线索?
非常感谢
答案 0 :(得分:3)
问题是原始文件是使用WAL选项创建的(现在是OS X Mavericks和iOS 7上的默认选项)。为了能够使用NSReadOnlyPersistentStoreOption,您需要创建一个关闭WAL的文件。您需要将此指令添加到iOS项目中:
NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES], NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"}}
以及使用创建原始文件的项目。 E.I.将您的数据重新导入到使用以下设置的NSSQLitePragmasOption创建的NSPersistantStore文件中:
NSDictionary *storeOptions = @{NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"}};
我认为这是实现中的一个错误,因为没有技术原因导致此错误,因为Core Data处理使用WAL创建的文件上的元数据的方式,文件不会被加载。
答案 1 :(得分:2)
要打开只读存储,您应该使用
NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : @YES};
而不是@NO
。
答案 2 :(得分:2)
我认为您可以通过先将商店复制到文档目录来轻松解决问题。然后你可以传递只读选项(没关系,你可以不写它)。
至少这可能是一个很好的测试,看看你是否可以隔离这个问题..
我认为崩溃的原因可能是因为新版本的SQLite在访问商店时会创建另外两个文件。因为捆绑不可写,所以你会崩溃。
答案 3 :(得分:0)
在swift 3.0中,使用以下内容初始化持久性存储协调器:
fileprivate lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
var coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let bundlePath = Bundle.main.path(forResource: "TrackWaypoints", ofType: ".sqlite")
let bundleURL = URL(fileURLWithPath: bundlePath!)
let hi = [NSReadOnlyPersistentStoreOption:true, NSSQLitePragmasOption: ["journal_mode": "delete"]] as [String: Any]
let store = try! coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: bundleURL, options: hi)
return coordinator
}()