【问题标题】:function with closure not working correctly闭包功能无法正常工作
【发布时间】:2020-08-02 22:55:40
【问题描述】:

不幸的是,在我的 swiftUI 社交应用程序中,我使用 firebase 作为后端 我发现有时侦听器(我不知道为什么)会下载 2/3 次相同的更改,因此在 stackOverflow 的帮助下,我想出了以下功能,以便侦听更改并将其发布到视图上。

 func getuserConfirmFriend(userLoggato: UserModel, onSuccess: @escaping([UserModel]) -> Void, onError: @escaping(_ errorMessage: String) -> Void, newPendingUser: @escaping(UserModel) -> Void, userRemoved: @escaping(UserModel) -> Void , listener: @escaping(_ listenerHandle: ListenerRegistration) -> Void){
           let listenerRegistration = db.collection("user").document(userLoggato.userID).collection("confimFriend").addSnapshotListener(includeMetadataChanges: false) { documentSnapshot, error in
              var userConfirmFriendsArray = [UserModel]()
               guard let snapshot = documentSnapshot else { return }
               
               snapshot.documentChanges.forEach { (documentChange) in
                   switch documentChange.type {
                   case .added :
                       let dict = documentChange.document.data()
                       let name = dict["name"] as? String ?? "na name"
                       let surname = dict["surname"] as? String ?? "na name"
                       let email = dict["email"] as? String ?? "na name"
                       let userLevel = dict["adminLevel"] as? String ?? "unable to get admin level"
                       let idUser = dict["userID"] as? String ?? "no ID"
                       let position1 = dict["position"] as? String ?? "na preferance position"
                       let position2 = dict["position2"] as? String ?? "na preferance position"
                       let vote = dict["vote"] as? Int ?? 0
                       self.downloadImageForAdmin(userID: idUser) { (urlImage) in
                           let utente = UserModel(name: name, surname: surname, email: email, userID: idUser, adminLevel: userLevel, immagine: urlImage, position: position1, position2: position2, vote: vote)
                           
                           newPendingUser(utente)
                           userConfirmFriendsArray.append(utente)
                          // if I put onSuccess here it work but keep duplicating the result
                       }
                       print("CONFIRM User Added")
                   case .modified :
                       //implements action (new escaping)
                       
                       print("CONFIRM User Modified ")
                   case .removed :
                     print("CONFIRM User Removed")
                       let dict = documentChange.document.data()
                       let name = dict["name"] as? String ?? "na name"
                       let surname = dict["surname"] as? String ?? "na name"
                       let email = dict["email"] as? String ?? "na name"
                       let userLevel = dict["adminLevel"] as? String ?? "unable to get admin level"
                       let idUser = dict["userID"] as? String ?? "no ID"
                       let position1 = dict["position"] as? String ?? "na preferance position"
                       let position2 = dict["position2"] as? String ?? "na preferance position"
                       let vote = dict["vote"] as? Int ?? 0
                       self.downloadImageForAdmin(userID: idUser) { (urlImage) in
                           let utente = UserModel(name: name, surname: surname, email: email, userID: idUser, adminLevel: userLevel, immagine: urlImage, position: position1, position2: position2, vote: vote)
                           userRemoved(utente)
                       }
                   }
                   
                   
               }
               
              onSuccess(userConfirmFriendsArray)
 // Problem Here, not working this closure onSuccess
// Any reason why this closure always return an empty array?? should be filled on .added case
           }
           listener(listenerRegistration)
       }

我发现的问题是:据我所知,关闭 onSuccess 应该放在 forEach 之后。 像这样我可以使用 userConfirmFriendsArray:[UserModel] (请参阅我对代码的评论) 但看起来它总是返回一个空数组,为什么???如果 case . added 将用户追加到里面 userConfirmFriendsArray。

下面是我如何使用 getuserConfirmFriend()


func loadUserConfirmFriends(userLoggato: UserModel){
        
        self.userConfirmFriends = []
//        self.isLoading = true
        
        getuserConfirmFriend(userLoggato: userLoggato, onSuccess: { (users) in
            if self.userConfirmFriends.count == 0 {
            self.userConfirmFriends = users
            }
//        self.isLoading = false
        },
                             
        onError: { (errorMessage) in
        print("Error Message \(errorMessage)")
        },
        
        newPendingUser: { (user) in
            if self.userConfirmFriends.count > 0 {
            self.userConfirmFriends.append(user)
            }
        }, userRemoved: {(userRemoved) in
            
            let index = self.userConfirmFriends.firstIndex { (user) -> Bool in
                
                userRemoved.userID == user.userID
            }
            if index == nil {
                return
            } else {
            if self.userConfirmFriends.count >= 1 {
                self.userConfirmFriends = []
            } else {
                self.userConfirmFriends.remove(at: index!)}}
        })
        { (listener) in
        self.listener = listener
        }
    }

为了查看更改,我必须将 onSuccess(userConfirmFriendsArray) 闭包放在案例中。添加:,但为什么?不能放在 forEach 之后?如果我放在那里总是给我一个空数组。

谢谢

【问题讨论】:

    标签: swift firebase google-cloud-firestore


    【解决方案1】:

    因为snapshot.documentChanges.forEach 做事并在不同的线程中调用它们的闭包异步

    所以当您在snapshot.documentChanges.forEach 之后调用onSuccess(userConfirmFriendsArray) 行时,尚未调用闭包

    你有 self.downloadImageForAdmin(userID: idUser) 在不同的线程中异步调用闭包

    你可以阅读如何multithreading work

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-23
      • 2013-11-06
      • 2013-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多