SwiftUI SQLite ForEach данные списка - PullRequest
       13

SwiftUI SQLite ForEach данные списка

1 голос
/ 16 октября 2019

Я пытаюсь интегрировать базу данных 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 ()..

1 Ответ

1 голос
/ 17 октября 2019

Я обнаружил, как это сделать:

в моем рабочем файле SQLite, мне нужно было создать структуру для представления модели данных:

struct TestDataModel: Hashable {
    let id: Int
    let name: String
    let email: String
}

Затем в моем вспомогательном классе мойФункция загружает данные в массив объектов TestDataModel. Затем функция возвращает массив следующим образом:

    func listUsers2() ->  [TestDataModel]  {
         print("Listed Users")
        var theseVars = [TestDataModel]()
         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])")
                theseVars.append(TestDataModel(id: user[self.id], name: user[self.name], email: user[self.email]))
            }
         } catch {
             print(error)
         }
         return theseVars
     }

Затем в моем представлении SwiftUI я могу использовать массив объектов TestDataModel, как обычно:

            ForEach (myData.listUsers2(), id: \.self) { record in
                Text(record.email)

            }

Это работает, не уверенесли это самый элегантный подход, но результаты хорошие ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...