将 SQLite 数据库附加到应用程序
Attaching SQLite database to an application
我的应用程序应该使用 SQLite 数据库,我想将其插入到应用程序中。 sqlite 文件直接位于应用程序文件夹中(您可以在屏幕截图中看到)。如果我在 let storeUrl = URL(fileURLWithPath:FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Songbook/Model.sqlite")
行中添加完整路径,则应用程序将从数据库中读取数据。但是如果我只键入 Model.sqlite,应用程序不会读取。我不能在应用程序的最终版本中这样保留它。请建议我做错了什么。以下是完整代码。
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "Model")
let storeUrl = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Spiewnik/Spiewnik/Model.sqlite")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
enter image description here
更新数据:
我的代码现在看起来像这样,在模拟器中一切正常。但是,在 phone 上,数据库是空的。
static let shared = PersistenceController()
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "Model")
let dbName = "Model.sqlite"
let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
if !FileManager.default.fileExists(atPath: dbUrl.path) {
//move the file
do {
if let fileURL = Bundle.main.url(forResource: "Model", withExtension: "sqlite"){
try FileManager.default.copyItem(at: fileURL, to: dbUrl)
}
} catch {
print(error)
fatalError(error.localizedDescription)
}
}
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: dbUrl)]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
let documentsDirectory = paths[0]
return documentsDirectory
}
您似乎正在尝试从应用程序的捆绑包中加载数据库,这会出现问题,因为捆绑包文件不可写。相反,您需要将其复制到您可以 read/write 访问的位置。一种可能是应用程序的文档目录(或库目录,这在 macOS 上很常见)。
首先,您需要能够获得该目录的 URL:
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
let documentsDirectory = paths[0]
return documentsDirectory
}
然后,检查数据库是否已经存在。如果没有,请复制您的捆绑文件:
let dbName = "Model.sqlite"
let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
if !FileManager.default.fileExists(atPath: dbUrl.path) {
//move the file
do {
try FileManager.default.copyItem(at: Bundle.main.url(forResource: "Model", withExtension: "sqlite")!, to: dbUrl)
} catch {
print(error)
fatalError(error.localizedDescription)
}
}
//load your database from dbUrl here
然后,您可以使用 dbUrl
并从您现在复制的文件加载数据库。
我的应用程序应该使用 SQLite 数据库,我想将其插入到应用程序中。 sqlite 文件直接位于应用程序文件夹中(您可以在屏幕截图中看到)。如果我在 let storeUrl = URL(fileURLWithPath:FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Songbook/Model.sqlite")
行中添加完整路径,则应用程序将从数据库中读取数据。但是如果我只键入 Model.sqlite,应用程序不会读取。我不能在应用程序的最终版本中这样保留它。请建议我做错了什么。以下是完整代码。
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "Model")
let storeUrl = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Spiewnik/Spiewnik/Model.sqlite")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
enter image description here
更新数据: 我的代码现在看起来像这样,在模拟器中一切正常。但是,在 phone 上,数据库是空的。
static let shared = PersistenceController()
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "Model")
let dbName = "Model.sqlite"
let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
if !FileManager.default.fileExists(atPath: dbUrl.path) {
//move the file
do {
if let fileURL = Bundle.main.url(forResource: "Model", withExtension: "sqlite"){
try FileManager.default.copyItem(at: fileURL, to: dbUrl)
}
} catch {
print(error)
fatalError(error.localizedDescription)
}
}
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: dbUrl)]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
let documentsDirectory = paths[0]
return documentsDirectory
}
您似乎正在尝试从应用程序的捆绑包中加载数据库,这会出现问题,因为捆绑包文件不可写。相反,您需要将其复制到您可以 read/write 访问的位置。一种可能是应用程序的文档目录(或库目录,这在 macOS 上很常见)。
首先,您需要能够获得该目录的 URL:
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
let documentsDirectory = paths[0]
return documentsDirectory
}
然后,检查数据库是否已经存在。如果没有,请复制您的捆绑文件:
let dbName = "Model.sqlite"
let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
if !FileManager.default.fileExists(atPath: dbUrl.path) {
//move the file
do {
try FileManager.default.copyItem(at: Bundle.main.url(forResource: "Model", withExtension: "sqlite")!, to: dbUrl)
} catch {
print(error)
fatalError(error.localizedDescription)
}
}
//load your database from dbUrl here
然后,您可以使用 dbUrl
并从您现在复制的文件加载数据库。