如何在结构中正确显示来自 Firestore 的数据?

Posted

技术标签:

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

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

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

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

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

    输入“AAA”并点击[添加]按钮→将显示AAA 输入“BBB”并点击[添加]按钮→将显示BBB 输入“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 elsereturn

            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 应用

【问题讨论】:

【参考方案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 elsereturn
            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()
        
    

【讨论】:

以上是关于如何在结构中正确显示来自 Firestore 的数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在颤动中显示来自firestore的特定文档详细信息

如何在 Android 的 RecyclerView 中显示来自 Firestore 的数据?

如何在网站中显示来自 Firestore 下载 URL 的图像

Java Firestore Android 在查询中使用数组列表来显示来自关注用户的帖子

Java Firestore Android 在查询中使用数组列表来显示来自关注用户的帖子

如何从 Firestore 访问和显示正确的字符串?