【问题标题】:How to display data from Firestore at struct correctly?如何在结构中正确显示来自 Firestore 的数据?
【发布时间】:2021-05-22 05:11:47
【问题描述】:

我目前正在使用SwiftUIFirebase(FirebaseFirestoreSwift) 开发一个应用程序。

显示View时,想从Firestore获取数据并显示,但显示的数据不正确。

在下面视图的屏幕上,如果我输入一个标题并点击[添加],我希望输入的内容会保存在FireStoreCollection中,然后Documents中的所有Documents @ 将被获取并显示。 但它不能很好地工作。

例如,如果我输入如下数据:

  1. 输入“AAA”并点击[添加]按钮→将显示AAA
  2. 输入“BBB”并点击[添加]按钮→将显示BBB
  3. 输入“CCC”并点击[添加]按钮→将显示BBB

然后,如果我在Firebase 控制台上检查数据,我可以确认它已保存为您输入的内容(AAA、BBB、CCC)。

我该如何解决这个问题?


代码如下:

import SwiftUI
import Firebase
import FirebaseFirestoreSwift

struct GetDataTest: View {

    @State var items:[Item] = []
    @State var title:String = ""

    var body: some View {
        VStack{
            List{
                ForEach(self.items.indices, id: \.self){index in

                    ListRowTest(
                        title:self.items[index].title
                    )

//                    Text(self.items[index].title)
//                        .font(.title)
//                        .fontWeight(.bold)
                }
            }

            Button(action: {
                self.getAllItems()
            }, label: {
                Text("Update")
            })

            TextField("Enter titel",text:self.$title)
                .textFieldStyle(RoundedBorderTextFieldStyle())

            Button(action: {

                let item = Item(title: self.title)

                self.addItem(item: item){ (status) in
                    self.getAllItems()
                }
                
                self.title = ""
            }, label: {
                Text("Add")
            })
        }
        .onAppear{
            self.getAllItems()

        }
    }

    func getAllItems(){

        self.items = []

        let ref = Firestore.firestore()
        
        ref.collection("Items").getDocuments{
            (snap, err) in
            guard let docs = snap else{return}

            docs.documentChanges.forEach{ (doc) in
                let item = try! doc.document.data(as:Item.self)
                self.items.append(item!)
            }
        }
    }

    func addItem(item:Item , completion:@escaping (Bool) -> ()){

        let ref = Firestore.firestore()

        do{
            let _ = try
                ref.collection("Items").addDocument(from: item){ (error) in
                    if error != nil{
                        completion(false)
                        return
                    }
                    completion(true)
                }
        }catch{
            print(error.localizedDescription)
            completion(false)
        }
    }
}


struct ListRowTest: View {

    @State var title:String

    var body: some View {
        HStack{
            Text(title)
                .font(.title)
                .fontWeight(.bold)
        }
    }
}


struct Item : Identifiable,Codable {

    @DocumentID var id : String?
    var title : String

    enum CodingKeys : String,CodingKey {
        case id
        case title
    }
}

            ListRowTest(
                title:self.items[index].title
            )

如果我将上面的代码更改如下,它将正确显示。 但是我想用struct作为组件,所以这个方法解决不了。

            Text(self.items[index].title)
                .font(.title)
                .fontWeight(.bold)

Xcode:版本 12.3

iOS:14.0

生命周期:SwiftUI 应用

【问题讨论】:

    标签: firebase google-cloud-firestore swiftui


    【解决方案1】:

    使用 Firebase/Firestore 确实是在处理异步函数。 所以我会重组你的代码以使用封装的 ObservableObject 项目和数据库调用,例如这样的:

    class ItemsModel: ObservableObject {
        @Published var items = [Item]()
        private var ref = Firestore.firestore()
        
        func getAllItems() {
            ref.collection("Items").getDocuments{ (snap, err) in
                guard let docs = snap else{return}
                docs.documentChanges.forEach{ (doc) in
                    let item = try! doc.document.data(as:Item.self)
                    self.items.append(item!)
                }
            }
        }
        
        func addItem(item: Item, completion:@escaping (Bool) -> ()){
            do {
                let _ = try
                    ref.collection("Items").addDocument(from: item){ (error) in
                        if error != nil{
                            completion(false)
                            return
                        }
                        self.items.append(item!)  // <----
                        completion(true)
                    }
            } catch {
                print(error.localizedDescription)
                completion(false)
            }
        }
    }
    struct GetDataTest: View {
        @ObservedObject private var itemsModel = ItemsModel()  // <----
        @State var title:String = ""
    
        var body: some View {
            VStack{
                List{
                    ForEach(itemsModel.items.indices, id: \.self){ index in
                        ListRowTest(title: itemsModel.items[index].title)
                    }
                }
                Button(action: {
                    itemsModel.getAllItems()
                }, label: {
                    Text("Update")
                })
                TextField("Enter titel",text:self.$title).textFieldStyle(RoundedBorderTextFieldStyle())
                Button(action: {
                    let item = Item(title: self.title)
                    itemsModel.addItem(item: item) { error in
                        // deal with error here
                    }
                    self.title = ""
                }, label: {
                    Text("Add")
                })
            }
            .onAppear{
                itemsModel.getAllItems()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-03
      • 2018-08-22
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 2020-07-11
      • 1970-01-01
      相关资源
      最近更新 更多