如何通过在 swiftui 中使用 ID 引用来覆盖可识别对象?
How do I overwrite an identifiable object by refrencing it with an ID in swiftui?
我已经简化了我的代码,以便更容易看到我正在尝试做什么,我正在构建一个评级提要,这些评级来自我“关注”的任何人的 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, review: review, 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, review: review, 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)
我已经简化了我的代码,以便更容易看到我正在尝试做什么,我正在构建一个评级提要,这些评级来自我“关注”的任何人的 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, review: review, 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, review: review, 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)