【发布时间】:2020-02-13 15:27:17
【问题描述】:
我正在尝试将 SQLite 数据库 (with SQLite.swift) 集成到我的项目中(因为我未恢复的 CoreData 明显限制引用了 here。
我有一个帮助文件,其中包含一个我实例化的类来完成与 SQLite 查询有关的所有繁重工作。
我不知道如何在 SwiftUI 中的 ForEach 语句中获取该数据,比如一个简单的数据库内容列表。
我试图从运行查询的函数中设置一个返回值,但它的返回类型是AnySequence<Row>,我不知道该怎么做。当我在获取数据后尝试返回它时,我收到关于不返回失败的错误(可以理解)。在这种情况下,不知道如何返回空白 AnySequence<Row>。请参阅下面的代码。
有什么想法吗?
来自帮助类的代码(按照Kilo Loco's YouTube video 的一些说明构建:
import Foundation
import SQLite
class DataModel {
var database: Connection!
let usersTable = Table("users")
let id = Expression<Int>("id")
let name = Expression<String>("name")
let email = Expression<String>("email")
var dataDict = [Dictionary<String, String>()]
init() {
do {
let documentDirectory = try FileManager.default.url(for: .applicationSupportDirectory, in: .allDomainsMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory.appendingPathComponent("users").appendingPathExtension("sqlite3")
let database = try Connection(fileUrl.path)
self.database = database
print("Database initialized at path \(fileUrl)")
} catch {
print(error)
}
}
func createTable() {
print("Create Tapped")
let createTable = self.usersTable.create { (table) in
table.column(self.id, primaryKey: true)
table.column(self.name)
table.column(self.email, unique: true)
}
do {
try self.database.run(createTable)
print("Table Created")
} catch {
print(error)
}
}
func insertRecord(name: String, email: String) {
let insertRecord = self.usersTable.insert(self.name <- name, self.email <- email)
do {
try self.database.run(insertRecord)
print("record added")
} catch {
print(error)
}
}
func listUsers() {
print("Listed Users")
do {
let users = try self.database.prepare(self.usersTable)
for user in users {
print("User ID: \(user[self.id]), UserName: \(user[self.name]), Email: \(user[self.email])")
}
} catch {
print(error)
}
}
}
和简单的 SwiftUI 内容视图
import SwiftUI
let myData = DataModel()
struct ContentView: View {
@State var name: String = ""
@State var email: String = ""
var body: some View {
VStack {
TextField("Enter Name", text: self.$name)
TextField("Enter email", text: self.$email)
Button(action: {
myData.insertRecord(name: self.$name.wrappedValue, email: self.$email.wrappedValue)
}) {
Text("Insert Record")
}
Button(action: {
myData.createTable()
}) {
Text("Create Table")
}
Button(action: {
myData.listUsers()
}) {
Text("List users")
}
}
}
}
理论上,我希望能够在我的 VStack 中做类似的事情:
ForEach (myData.listUsers, id: \.self) { record in
Text("UserName \(record.userName)")
}
我试图让 listUsers 函数返回它的结果,以便可以像这样使用它,但效果并不好..
更新 #1
尝试让函数返回数据,然后我可以在 SwiftUI 视图中对其进行迭代。我正在尝试这个:
func listUsers() -> (Int, String, String) {
print("Listed Users")
do {
let users = try self.database.prepare(self.usersTable)
for user in users {
print("User ID: \(user[self.id]), UserName: \(user[self.name]), Email: \(user[self.email])")
return (user[self.id], user[self.name], user[self.email])
}
} catch {
print(error)
}
return (0, "No Name", "No Email")
}
然后在我试图调用的视图中:
let response = myData.listUsers()
for resp in response {
Text(resp.name)
}
然后我得到错误:
类型'(Int, String, String)'不符合协议'Sequence'
更新 #2
Holy C*&@ - 多么痛苦..
我能够让函数返回我可以使用的东西,但这绝对不是最有效的方法。知道如何才能做得更好:
我现在的功能是:
func listUsers() -> [Dictionary<String,Any>] {
print("Listed Users")
do {
let users = try self.database.prepare(self.usersTable)
for user in users {
print("User ID: \(user[self.id]), UserName: \(user[self.name]), Email: \(user[self.email])")
dataDictArray.append(["id":user[self.id], "name":user[self.name], "email":user[self.email]])
}
} catch {
print(error)
}
return dataDictArray
}
}
它返回一个字符串字典数组:任何(因为我在我的数据库中混合了字符串和整数。那么我的函数看起来像:
let response = myData.listUsers()
print(response)
for dicts in response {
for record in dicts {
if (record.key.datatypeValue == "name") {
print("Record Key: \(record.key)")
print("Record Value: \(record.value)")
}
}
}
}) {
Text("List users")
}
那么它在做什么,很荒谬,就是循环遍历数组,然后循环遍历字典得到键值对..
只是感觉很麻烦而且过于复杂。
- 仍然无法弄清楚如何将其放入实际视图中。我可以将输出打印到日志中,但不能在 Text() 标记中..
【问题讨论】:
标签: ios swift xcode sqlite swiftui