问题描述
该文件需要稍后读取和写入。在 Android 上,我使用了 Room & RoomAssetHelper。
我了解我需要将其包含在项目资产中的基本逻辑,然后在首次启动时将其复制到应用可访问的某个位置。但我想避免手动编写这些东西并冒犯错误的风险(我对读取文件和数据库不太有信心)。
我找到的所有答案都来自人们就如何为此手动编码逻辑提供快速而肮脏的建议。我想在干净和专业的水平上做到这一点。
是否有一个图书馆可以为我完成大部分“有风险”的工作?
(意思是导入并复制 .sqlite 文件,这样我就可以开始在我的代码中使用它了)
我找到了 GRDB.swift,但我不知道它是否支持预填充文件。
解决方法
请不要再寻找一个可以自动为您完成所有这些工作的神奇图书馆了。
如果没有任何 SQLite 库,您需要自己做什么?
-
将预填充的
database.sqlite
作为资产添加到项目中。 -
当应用启动时,检查
database.sqlite
文件是否存在于预期位置(例如在应用的文档目录中)。您可以使用FileManager
API 进行检查。 -
如果文件存在于预期路径中,则没有问题,无需复制任何文件。
-
如果
database.sqlite
文件在预期路径中不存在,您需要使用database.sqlite
API 在该路径中复制您的FileManager
文件。
注意: 请注意,在此步骤中,您可能会在复制文件时遇到错误。大多数情况下不应该发生这种情况。在极少数情况下,您应该相应地调整您的应用程序 - 以某种方式向用户表明初始化失败,释放手机上的一些空间,重新启动应用程序等。
步骤 2-4 需要在每次应用启动时检查 - 将此逻辑放在靠近应用启动过程的某个位置。如果按照上述所有说明进行操作并且您通过第 3 步或第 4 步成功,那么您现在就拥有了所需的 database.sqlite
文件。
SQLite 库从何而来?
此时,您可以使用任何适合您的目的并且您感觉舒服的库。
正如您提到的 GRDB.swift
,它允许您为数据库文件指定自定义路径。复制粘贴当前版本的最小设置代码以供参考。
import GRDB
// 1. Open a database connection
let dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")
// 2. Define the database schema
try dbQueue.write { db in
try db.create(table: "player") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name",.text).notNull()
t.column("score",.integer).notNull()
}
}
// 3. Define a record type
struct Player: Codable,FetchableRecord,PersistableRecord {
var id: Int64
var name: String
var score: Int
}
// 4. Access the database
try dbQueue.write { db in
try Player(id: 1,name: "Arthur",score: 100).insert(db)
try Player(id: 2,name: "Barbara",score: 1000).insert(db)
}
let players: [Player] = try dbQueue.read { db in
try Player.fetchAll(db)
}