SwiftData无法使用预填充持久化存储的问题求助
解决SwiftData真机加载预填充数据库时"attempt to write a readonly database"错误
问题原因
真机上App的主Bundle是只读目录,直接从Bundle加载Model.store时,SwiftData会尝试对这个文件执行写入操作(比如模型自动迁移、生成辅助文件),这在真机上被系统禁止,从而触发"attempt to write a readonly database"错误。而模拟器的沙盒机制相对宽松,允许对Bundle内文件进行写入,所以不会报错。
解决方案
必须先将Bundle中的预填充数据库复制到App的可读写目录(比如Documents目录),再加载这个复制后的文件。修改你的TestSeededApp初始化代码如下:
import SwiftUI import SwiftData @main struct TestSeededApp: App { let container: ModelContainer var body: some Scene { WindowGroup { ContentView() } .modelContainer(container) } init() { do { // 获取Bundle中的源数据库文件 guard let sourceStoreURL = Bundle.main.url(forResource: "Model", withExtension: "store") else { fatalError("Model.store not found in main bundle") } // 定义Documents目录中的目标路径 let documentsDirectory = URL.documentsDirectory let targetStoreURL = documentsDirectory.appending(path: "Model.store") let fileManager = FileManager.default // 仅当目标文件不存在时复制,避免每次启动重复复制 if !fileManager.fileExists(atPath: targetStoreURL.path()) { try fileManager.copyItem(at: sourceStoreURL, to: targetStoreURL) } // 使用可读写目录中的数据库初始化ModelContainer let config = ModelConfiguration(url: targetStoreURL) container = try ModelContainer(for: Entity.self, configurations: config) } catch { fatalError("Failed to initialize model container: \(error.localizedDescription)") } } }
额外注意事项
- 确认
Model.store已正确添加到SwiftData项目的Target Membership中,否则Bundle无法找到该文件 - 预填充数据库的模型结构必须和当前SwiftData的
Entity完全一致,否则SwiftData会触发自动迁移逻辑,再次尝试写入文件 - 如果后续需要更新预填充数据,可以在复制前检查版本号(比如添加一个版本文件),避免覆盖用户已修改的数据
内容的提问来源于stack exchange,提问作者Dovahkiin
相关产品推荐
相关产品推荐

