SwiftIU/Firebase:如何从 Firebase 实时更新用户列表并将其反映在 UI 中?
SwiftIU/Firebase: How to update lists of users from Firebase in real time and have it reflect in the UI?
https://www.loom.com/share/de410c2626644dd796ad407fcee7e5c7
^^^ 我附上了一个 loom 视频,演示了我面临的错误以及我目前拥有的代码。
问题是 UI 不会立即更新,这可能会使用户感到困惑。所有关于正确更新后端函数的代码(它的 UI 更新不能正常工作),我很确定它与我调用函数或函数的方式有关本身。
如有任何帮助,我们将不胜感激!
@Published var userRequestInboxUsers = [User]()
@Published var emergencyContactUsers = [User]()
// function to fetch the user requests
func fetchTheUsersRequests() {
guard let uid = user.id else { return }
let query = COLLECTION_FOLLOWERS.document(uid).collection("inbox").whereField(
"currentStatus", isEqualTo: "isPending")
query.addSnapshotListener(includeMetadataChanges: true) { snapshot, error in
if let error = error {
print("There was an error querying the inbox requests: \(error.localizedDescription)")
} else {
for request in snapshot!.documents {
COLLECTION_USERS.document(request.documentID).getDocument { snapshot, error in
if let error = error {
print("There was an error fetching the user data: \(error)")
} else {
DispatchQueue.main.async {
guard let userRequestInInbox = try? snapshot?.data(as: User.self) else { return }
self.userRequestInboxUsers.append(userRequestInInbox)
}
}
}
}
}
}
}
//function that fetches the users contacts (request that have been approved)
func fetchTheUsersContacts() {
guard let uid = user.id else { return }
let query = COLLECTION_FOLLOWERS.document(uid).collection("inbox").whereField(
"currentStatus", isEqualTo: "emergencyContact")
query.addSnapshotListener(includeMetadataChanges: true) { snapshot, error in
if let error = error {
print("There was an error querying the emergency contacts: \(error.localizedDescription)")
} else {
for userContact in snapshot!.documents {
COLLECTION_USERS.document(userContact.documentID).getDocument { snapshot, error in
if let error = error {
print("There was an error fetching the user data: \(error)")
} else {
DispatchQueue.main.async {
guard let userEmergencyContactsInInbox = try? snapshot?.data(as: User.self) else {
return
}
self.emergencyContactUsers.append(userEmergencyContactsInInbox)
}
}
}
}
}
}
}
我尝试在每次出现视图时调用该函数,但这会导致重复的结果。
我目前正在使用快照侦听器来获得实时访问,但即使这样也不起作用。
我已经构建了我的后端以包含一个联系人子集合和一个请求子集合,但是我遇到了更多代码行的相同问题...
我考虑过切换到 async/await,但我更希望我的应用程序兼容 ios 14 岁以上,而不仅仅是 15 岁及以上。
我可以尝试使用严格的 Combine 而不是回调,但我认为这不会有效地解决问题。
问题是您将文档附加到已发布的 属性。这将导致重复条目。
相反,只需将映射文档的 所有 分配给 emergencyContactUsers
属性.
查看 Mapping Firestore Data in Swift - The Comprehensive Guide | Peter Friese 了解更多详情。我的博客上还有一些关于 Firestore 和 SwiftUI 的其他帖子可能会有用。
至于您看到的“重复 ID”警告 - 这实际上也可能导致该问题。 SwiftUI 列表要求所有列表项都具有唯一 ID,而您的用户对象似乎可能没有唯一 ID。这可能是因为您在已发布的属性中拥有同一用户的多个副本,或者您的 User
结构无法识别。
我注意到您正在使用 DispatchQueue.async
来确保您在主线程上。这不是必需的,因为 Firestore 会确保在主线程上调用您的代码。有关解释,请参阅 https://twitter.com/peterfriese/status/1489683949014196226。
另外 - 我很好奇你在视频开头所说的找不到相关文档。我们一直在寻找改进 Firebase 文档的方法 - 您寻找了什么/没有找到什么?
https://www.loom.com/share/de410c2626644dd796ad407fcee7e5c7
^^^ 我附上了一个 loom 视频,演示了我面临的错误以及我目前拥有的代码。
问题是 UI 不会立即更新,这可能会使用户感到困惑。所有关于正确更新后端函数的代码(它的 UI 更新不能正常工作),我很确定它与我调用函数或函数的方式有关本身。
如有任何帮助,我们将不胜感激!
@Published var userRequestInboxUsers = [User]()
@Published var emergencyContactUsers = [User]()
// function to fetch the user requests
func fetchTheUsersRequests() {
guard let uid = user.id else { return }
let query = COLLECTION_FOLLOWERS.document(uid).collection("inbox").whereField(
"currentStatus", isEqualTo: "isPending")
query.addSnapshotListener(includeMetadataChanges: true) { snapshot, error in
if let error = error {
print("There was an error querying the inbox requests: \(error.localizedDescription)")
} else {
for request in snapshot!.documents {
COLLECTION_USERS.document(request.documentID).getDocument { snapshot, error in
if let error = error {
print("There was an error fetching the user data: \(error)")
} else {
DispatchQueue.main.async {
guard let userRequestInInbox = try? snapshot?.data(as: User.self) else { return }
self.userRequestInboxUsers.append(userRequestInInbox)
}
}
}
}
}
}
}
//function that fetches the users contacts (request that have been approved)
func fetchTheUsersContacts() {
guard let uid = user.id else { return }
let query = COLLECTION_FOLLOWERS.document(uid).collection("inbox").whereField(
"currentStatus", isEqualTo: "emergencyContact")
query.addSnapshotListener(includeMetadataChanges: true) { snapshot, error in
if let error = error {
print("There was an error querying the emergency contacts: \(error.localizedDescription)")
} else {
for userContact in snapshot!.documents {
COLLECTION_USERS.document(userContact.documentID).getDocument { snapshot, error in
if let error = error {
print("There was an error fetching the user data: \(error)")
} else {
DispatchQueue.main.async {
guard let userEmergencyContactsInInbox = try? snapshot?.data(as: User.self) else {
return
}
self.emergencyContactUsers.append(userEmergencyContactsInInbox)
}
}
}
}
}
}
}
我尝试在每次出现视图时调用该函数,但这会导致重复的结果。
我目前正在使用快照侦听器来获得实时访问,但即使这样也不起作用。
我已经构建了我的后端以包含一个联系人子集合和一个请求子集合,但是我遇到了更多代码行的相同问题...
我考虑过切换到 async/await,但我更希望我的应用程序兼容 ios 14 岁以上,而不仅仅是 15 岁及以上。
我可以尝试使用严格的 Combine 而不是回调,但我认为这不会有效地解决问题。
问题是您将文档附加到已发布的 属性。这将导致重复条目。
相反,只需将映射文档的 所有 分配给 emergencyContactUsers
属性.
查看 Mapping Firestore Data in Swift - The Comprehensive Guide | Peter Friese 了解更多详情。我的博客上还有一些关于 Firestore 和 SwiftUI 的其他帖子可能会有用。
至于您看到的“重复 ID”警告 - 这实际上也可能导致该问题。 SwiftUI 列表要求所有列表项都具有唯一 ID,而您的用户对象似乎可能没有唯一 ID。这可能是因为您在已发布的属性中拥有同一用户的多个副本,或者您的 User
结构无法识别。
我注意到您正在使用 DispatchQueue.async
来确保您在主线程上。这不是必需的,因为 Firestore 会确保在主线程上调用您的代码。有关解释,请参阅 https://twitter.com/peterfriese/status/1489683949014196226。
另外 - 我很好奇你在视频开头所说的找不到相关文档。我们一直在寻找改进 Firebase 文档的方法 - 您寻找了什么/没有找到什么?