Sqlite 使用nsreadonlypersistentstore选项时崩溃

Sqlite 使用nsreadonlypersistentstore选项时崩溃,sqlite,core-data,ios7,Sqlite,Core Data,Ios7,我正在为我的应用程序使用位于MainBundle中的只读sqlite数据库。在PersistentStoreCoordinator中,我使用以下代码加载数据库: NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES]}; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentS

我正在为我的应用程序使用位于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}
CoreData:error:(14)位于/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/Applications.sqlite的数据库的I/O错误。SQLite错误代码:14,“无法打开数据库文件”
2014-03-22 20:45:34.346 GfxHotkeys3[1369:60b]核心数据:错误:在/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/Applications.sqlite处遇到数据库异常I/O错误。SQLite错误代码:14,“无法使用userInfo打开数据库文件”{
NSFilePath=“/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/Applications.sqlite”;
NSSQLiteErrorDomain=14;
}从存储中检查表名时:
2014-03-22 20:45:34.372 GfxHotkeys3[1369:60b]未解决的错误域=nscocaerorDomain代码=256“操作无法完成。(可可错误256)。”用户信息=0x155b01b0{NSUnderlyingException=位于/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/myapp.app/Applications.sqlite的数据库的I/O错误。sqlite错误代码:14,'无法打开数据库文件',NSSQLiteErrorDomain=14},ErrorDomain=nscocaerorDomain code=256“操作无法完成。(Cocoa错误256.)“UserInfo=0x155b01b0”{NSUnderlyingException=位于/var/mobile/Applications/4B81AEFE-03E6-4156-B52D-3452515FACAF/GfxHotkeys3.app/Applications.sqlite的数据库的I/O错误。sqlite错误代码:14,“无法打开数据库文件”,NSSQLiteErrorDomain=14}
通过nil-in-store选项,将在模拟器中运行应用程序,但不会在设备上运行(因为它无法在MainBundle上写入)

我可以通过将数据库复制到文档中并从那里加载来解决这个问题,但我想知道为什么会发生这种情况。我使用这个选项从MainBundle加载只读sqlite已有多年了,但在iOS 7中崩溃了

有什么线索吗


非常感谢

要打开只读存储,您应该使用

NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : @YES};

不要像您那样使用
@NO

要打开只读存储,您应该使用

NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : @YES};

我想你可以通过先将存储复制到documents目录来轻松解决这个问题。然后你可以传递只读选项或不传递只读选项(这没关系,你可以不写)

至少这可能是一个很好的测试,看看你是否可以隔离问题


我认为崩溃的原因可能是因为新版本的SQLite在访问存储时会创建另外两个文件。因为捆绑包不可写,所以会发生崩溃。

我认为您可以通过首先将存储复制到documents目录来轻松解决问题。然后您可以传递只读选项或不传递只读选项(没关系,你不能给它写信)

至少这可能是一个很好的测试,看看你是否可以隔离问题


我认为崩溃的原因可能是因为新版本的SQLite在访问存储时会创建另外两个文件。因为捆绑包不可写,所以会发生崩溃。

问题是原始文件是使用WAL选项创建的(现在在OS X Mavericks和iOS 7上是默认的)。若要使用nsreadonlypersistentstore选项,您需要创建一个已关闭的文件。您需要将此指令添加到iOS项目中:

NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES], NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"}}
以及在使用.E.i.创建原始文件的项目中,将数据重新导入到使用NSSQLitePragmas选项集创建的NSPersistantStore文件中,该选项设置为:

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

我认为这是实现中的一个错误,因为这个错误没有技术原因,文件没有加载,因为核心数据处理WAL创建的文件上的元数据。

< P>问题是原始文件是用WAL选项创建的(现在是OSX小牛和iOS 7上的默认值)。。若要使用nsreadonlypersistentstore选项,您需要创建一个已关闭的文件。您需要将此指令添加到iOS项目中:

NSDictionary *storeOptions = @{NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES], NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"}}
以及在使用.E.i.创建原始文件的项目中,将数据重新导入到使用NSSQLitePragmas选项集创建的NSPersistantStore文件中,该选项设置为:

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

我认为这是一个错误,因为没有错误的技术原因,文件没有加载,因为核心数据处理WAL创建的文件的元数据。

在SWIFT 3中,初始化您的持久存储协调器,用以下内容:

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
}()

在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
}()

上面示例中的输入错误。感谢您指出。已修复以避免混淆。代码在使用nsreadonlypersistentstoreption的设备上崩溃@YES@Nimrod7:文件名是否正确?请注意,设备上的文件系统区分大小写,因此“applications.sqlite”和“applications.sqlite”将是不同的文件。-如果您禁用WAL模式是否有帮助,如此处所述:?文件的大小写正确。禁用WAL模式没有帮助。在设备和服务器中崩溃simulator@Nimrod7:我刚刚发现了这个,它看起来与您的问题非常相似(我也给出了一个错误的答案:-)。请注意,禁用WAL模式是解决方案。问题看起来是一样的。iOS 6中的数据库工作正常,因此我想我必须使用iOS 6模拟器并禁用WAL模式,然后将db导入iOS 7项目。我将其标记为正确答案,这是对所发生情况的最完整的解释。感谢您在示例中指出此.typoe。感谢您指出。已修复以避免混淆。使用nsreadonlypersistentstoreption时,代码会在设备上崩溃@YES@Nimrod7:文件名是否正确?请注意,设备上的文件系统为case sen