如何通过在 swiftui 中使用 ID 引用可识别对象来覆盖它?

问题描述

我已经简化了我的代码,所以更容易看到我想要做什么,我正在构建一个评级提要,这些评级来自我“关注”的任何人的 firebase 文档

我想要做的就是每当 firebase 说我的评论有新更新时,更改可识别的,因为不得不重新加载我关注的每个人的每条评论

这是我的观点:

import SwiftUI
import Firebase

struct rating: Identifiable {
    var id: String
    var review: String
    var likes: Int
}

struct Home: View {
    
    @Observedobject var Feedviewmodel = Feedviewmodel()

    var body: some View {
        vstack{
                         
           ForEach(self.Feedviewmodel.allratings,id: \.id){ rating in
               Text(rating.review)
               Text("\(rating.likes)")
           }
        }
     }
}

这是我的 Feedviewmodel 函数

class Feedviewmodel: ObservableObject {

     @Published var following = ["qedXpEcaRLhIa6zWjfJC","1nDyDT4bIa7LBEaYGjHG","4c9ZSPTQm2zZqztNlVUp","YlvnziMdW8VfibEyCUws"]
     @Published var allratings = [rating]()

     init() {
         for doc in following {
              
              // For each person (aka doc) I am following we need to load all of it's ratings and connect the listeners
              getratings(doc: doc)
              initializeListener(doc: doc)

          }
      }


    func getratings(doc: String) {
        
        db.collection("ratings").document(doc).collection("public").getDocuments() { (querySnapshot,err) in
            
            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                
 
                // We have to use += because we are loading lots of different documents into the allratings array,allratings turns into our Feed of reviews.
                self.allratings += querySnapshot!.documents.map { queryDocumentSnapshot -> rating in
                   let data = queryDocumentSnapshot.data()
                   let id = ("\(doc)-\(queryDocumentSnapshot.documentID)")
                   let review = data["review"] as? String ?? ""
                   let likes = data["likes"] as? Int ?? 0

                   return rating(id: id,review: review,likes: likes)

                }
            }
      }


    func initializeListener(doc: String){
        
        db.collection("ratings").document(doc).collection("public")
            .addSnapshotListener { (querySnapshot,error) in
            
            guard let snapshot = querySnapshot else {
                print("Error listening for channel updates")
                return
            }

            snapshot.documentChanges.forEach { change in

                for document in snapshot.documents{

                   let data = document.data()
                   let id = ("\(doc)-\(document.documentID)")
                   let review = data["review"] as? String ?? ""
                   let likes = data["likes"] as? Int ?? 0

                   // I thought swiftui Identifiables would be smart enough to not add another identifiable if there is already an existing one with the same id,but I was wrong,this just duplicates the rating
                   // self.allratings.append(rating(id: id,likes: likes))

                   // This is my current solution,to overwrite the rating in the allratings array,however I can not figure out how to get the index of the changed rating
                   // "0" should be replaced with whatever rating index is being changed
                   self.allratings[0] = rating(id: id,likes: likes)

                }
            }
        }
     }

}

我想要的只是让每个评分的“喜欢”实时显示,并在有人喜欢某个评分时更新。这看起来很简单,但我对 swiftui 比较陌生,所以我可能完全不知道我是怎么做的。非常感谢任何帮助!

解决方法

经过一周的尝试,我终于明白了,希望这对某人有所帮助,如果您想覆盖数组中可识别的内容,请使用您的 id 查找索引。就我而言,我的 ID 是 firebaseCollectionID + firebaseDocumentID,因此这使它始终 100% 唯一,并且允许我从快照侦听器中引用它...

let index = self.allRatings.firstIndex { (Rating) -> Bool in
    Rating.id == id
}

然后通过执行以下操作覆盖它:

self.allRatings[index!] = Rating(id: id,review: review,likes: likes)