核心数据SQLite存储在更新后变为只读

时间:2014-06-04 16:15:09

标签: ios core-data

我有报告称用户在通过App Store更新后无法使用iOS应用程序,因为Core Data使用的SQLite数据库显然已成为只读状态。这发生在读/写持久性存储中,该存储保存在应用程序包的Documents文件夹中。

持久存储是在第一次登录应用时为每个用户从头开始创建的。其内容通过自定义渐进式管理对象模型迁移进行维护。碰巧的是,最近的版本没有迁移,因此应用程序启动后应该可以立即打开持久存储。

我们从用户收到的错误是相同的,它在升级完成后的流程启动早期发生。 userInfo对象的NSError就是我们在这种情况下捕获的内容:

NSSQLiteErrorDomain = 264;
NSUnderlyingException = "error during prepareSQL for SQL string 'SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA' : attempt to write a readonly database";

由于我们正在记录的内容以及我们如何管理日志文件存在一些缺点,因此我不确切地知道在打开持久性存储的过程中何时发生这种情况。我们正在使用UIManagedDocument但不通过iCloud共享任何文档。我假设在打开现有文档包时发生错误,但即便如此。 (因此,我对未来版本的日志记录进行了改进。)

我最接近再现错误的是使用iOS模拟器应用安装的文档包中的persistentStore-shm文件上的文件权限0444,然后使用{尝试SELECT语句{1}}命令行界面。在这种情况下的错误是sqlite3而不是SQLITE_CANTOPEN,所以我可能没有关于文件权限的理论。据我所知,SQLITE_READONLY无论如何都会自动修复文件权限。

我想知道的是,是否有人经历过类似的行为?如果是这样,有没有办法恢复,以便用户不必完成重新创建本地数据存储的过程?

2 个答案:

答案 0 :(得分:2)

我跑到这里,这很令人费解。事实证明,-shm文件,即预写日志的索引已被清除,需要重建。当将持久性存储加载到NSPersistentStoreCoordinator时,这似乎会自动发生。

如果您在执行此操作之前致电+[NSPersistentStore metadataForPersistentStoreWithURL:error:],我将会收到您报告的错误,并且返回值为nil

因此,对我有用的解决方案是尝试检索元数据,如果失败并出现错误,则将持久存储加载到NSPersistentStoreCoordinator以重建-shm。执行此操作后,调用metadataForPersistentStoreWithURL:error:将返回元数据,而不会发出只读错误。

答案 1 :(得分:1)

在选项中添加您自己的描述符,以(重新)启用历史记录跟踪...

在将商店作为容器设置的一部分加载之前执行以下操作:

let container = NSPersistentContainer(name: "YourDataStoreIdentifier" )
        
let description = container.persistentStoreDescriptions.first
// This allows a 'non-iCloud' sycning 
// container to keep track of changes 
// as if it was an iCloud syncing container

description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        
container.loadPersistentStores(...