Я пытаюсь интегрировать базу данных SQLite (с SQLite.swift) в мой проект (поскольку мои неоткрытые очевидные ограничения CoreData ссылаются на здесь .
Iveполучил вспомогательный файл с классом, который я создаю, чтобы выполнить всю тяжелую работу в отношении запросов SQLite.
Я не могу понять, как получить эти данные, скажем, простой список содержимогобазы данных, в оператор ForEach в SwiftUI.
Я попытался установить возврат из функции, выполняющей запрос, но его тип возвращаемого значения AnySequence<Row>
, и я не уверен, что с этим делатьКогда я пытаюсь вернуть его после извлечения данных, я получаю ошибки о невозможности возврата по ошибке (понятно). Не знаю, как вернуть пустое значение AnySequence<Row>
в этом случае. См. Код ниже.
Есть мысли?
Код из класса помощника (построен в соответствии с некоторыми инструкциями на видео Kilo Loco на YouTube :
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)» не соответствует протоколу «Последовательность»
Обновление № 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
}
}
, которая возвращает массив словаря строк: любой (потому что я смешиваю String и Int в моемЗатем моя функция выглядит следующим образом:
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 ()..