繁体   English   中英

SwiftUI 在异步 firebase 调用后不更新变量

[英]SwiftUI not updating variable after async firebase call

我正在尝试使用 firebase 和 swiftui 实现友谊模型。 在我的一个观点中,在它的出现调用中,我调用了一个检查友谊状态的方法,如下所示:

编辑:我已将 isFriend 设为已发布的变量,该变量应如下更新



class UserViewModel : ObservableObject{
    
     .... 
    //check friendship variabe
    @Published var isFriend = 0
 func checkFriendRequest(otherUserUID: String) -> Int{
        
        //0 if not found in friend list or friend request
        //1 means theyre friends
        //2 means that user sent self/me a friend request
        print("otherUserUID is \(otherUserUID)")
        var pendingFriendRequests: [String: Bool] = [:]
        self.ref.collection("Users").document(self.uid).getDocument(){
            (document, err) in
            
            if let err = err {
                print("Error getting documents \(err)")
            } else {
                pendingFriendRequests = document!.data()!["friends"] as! [String : Bool]
                
                print("pendingFriendRequests is \(pendingFriendRequests)")

                for key in pendingFriendRequests.keys {
                    if key == otherUserUID{
                        print("key is \(key) and value is \(pendingFriendRequests[key])")

                        if pendingFriendRequests[key] == true {
                            self.isFriend = 1
                        }else if pendingFriendRequests[key] == false {
                            self.isFriend = 2
                            
                        }
                    }
                }
            }
        }
        return self.isFriend
    }
}

在我的视图代码中,我想检查这个函数的返回值并更新应该在视图上的按钮的文本/操作,它看起来像下面这样:


struct OtherUser: View {
    @StateObject var userData = UserViewModel()

    var otherUserUID: String
    var otherUserName: String
    var otherUserUsername: String
    var otherUserPic: String
    
    @Environment(\.presentationMode) var present

    
    init(_ otherUserUID: String, _ otherUserName: String, _ otherUserUsername: String, _ otherUserPic: String){
        self.otherUserUID = otherUserUID
        self.otherUserName = otherUserName
        self.otherUserUsername = otherUserUsername
        self.otherUserPic = otherUserPic
        

    }
    var body: some View {
        ZStack(alignment: .top){
            Color("Black")
                .ignoresSafeArea()
            VStack {
                if (userData.checkFriendRequest(otherUserUID: otherUserUID)) == 1 {
                   //button for if returned 1
              }else if (userData.checkFriendRequest(otherUserUID: otherUserUID)) == 2 {
                   //button for if returned 2
              }else {
             
              }

            }
        }
    }
}

但是,当视图出现时,它会在异步 firebase 调用后自动返回 0 而不更新值。 我已经查找了其他解决方案并尝试了调度组,但他们似乎没有成功。 我知道它与 firebase 的异步性质有关,但希望得到一些帮助以了解如何改进这一点,以便变量 isFriend 得到更新,然后在视图出现之前返回。 谢谢你的帮助

SwiftUI 视图会根据其视图的状态自动触发更新。 由于 Firebase 调用是异步的,您不能期望对 fetch 函数的同步调用会返回正确的结果。

相反,您需要更新 Published 值(在主线程上),然后该值将向该值的所有订阅者广播更新消息。 SwiftUI 会自动处理 StateObject 或 ObservedObject 的订阅机制,并触发对视图主体的新请求。

要让您的代码与 SwiftUI 一起工作,请按如下方式调整 checkFriendRequest:

改变这个:

            if pendingFriendRequests[key] == true {
                self.isFriend = 1
            } else if pendingFriendRequests[key] == false {
                self.isFriend = 2
            }

To:(因为它会触发UI事件并且所有UI都必须在主线程上运行)

          DispatchQueue.main.async {
                if pendingFriendRequests[key] == true {
                    self.isFriend = 1
                } else if pendingFriendRequests[key] == false {
                    self.isFriend = 2
                }
          }

在您看来,将 VStack 更改为:

      VStack {
          if userData.isFriend == 1 {
               //button for if returned 1
          } else if userData.isFriend == 2 {
               //button for if returned 2
          } else {
         
          }
      }.onAppear() {
          userData.checkFriendRequest(otherUserUID: otherUserUID)
      }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM