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 文档的方法 - 您寻找了什么/没有找到什么?