异步未来承诺在 Swift 5 中不起作用

克里什

我正在尝试实现对函数 loadUserFromFirebase 的异步调用,并根据用户属性填充和返回一个数组,然后我用它来写入 Firebase 集合。

我正在尝试使用 Swift 的 Combine 框架使用 future 和 promises,但由于某种原因,receiveCompletion 和 receiveValue 没有被调用,因此我从异步函数调用中得到一个空数组。

这是我的代码:

var cancellable = Set<AnyCancellable>()
    func loadUserFromFirebase(groupUserIds: [String], handler: @escaping ([groupMate]) -> Void) {
        
        var groupmateID = 0
        var groupMates : [groupMate] = []
        print("groupUserIds: \(groupUserIds)" )
        
        for groupUserUID in groupUserIds {
            print("groupUserUID: \(groupUserUID)" )
            
            let future = Future<groupMate, Never> { promise in
                self.ref.collection("Users").document(groupUserUID).getDocument(){
                    
                    (friendDocument, err) in
                
                    if let err = err {
                            print("Error getting documents \(err)")
                    } else {
                      //  print("friendDocument: \(String(describing: friendDocument?.data()))" )

                        let groupUsername = (friendDocument?.data()?["username"]) as! String
                        let groupUID = (friendDocument?.data()?["uid"]) as! String
                        let groupName = (friendDocument?.data()?["name"]) as! String
                        let groupPic = (friendDocument?.data()?["imageurl"]) as! String

                        promise(.success(groupMate(id: groupmateID, uid: groupUID , name: groupName , username: groupUsername, pic: groupPic)))
                    }
                    
                    groupmateID += 1
                }
            }
            print("in receiveCompletion")

            future.sink(receiveCompletion: { completion in
                print("in receiveCompletion")
                print(1, completion)
                switch completion {
                    case .failure(let error):
                        print(3, error)
                        handler([])
                        return
                    case .finished:
                        break
                }
            },
            receiveValue: {
                print("in receiveValue")
                groupMates.append($0)
                print(groupMates)
                handler(groupMates)
            }).store(in: &cancellable)
        }
    }
    
    
    func creategroup(groupName: String){
        addedTogroupUsers.append(self.uid)
        
        print("here111")
        loadUserFromFirebase(groupUserIds: addedTogroupUsers) { groupMates in
            print("here222")

            let groupData: [String: Any] = [
                "groupName": "\(groupName)",
                "groupmates": groupMates
            ]
            print("here333 \(groupData)")

            print("groupMates are \(self.groupMates)")
            
            
            var groupref: DocumentReference? = nil
                groupref = self.ref.collection("groups").addDocument(data: groupData) { err in
                if let err = err {
                    print("Error adding document: \(err)")
                } else {
                    print("Document added with ID: \(groupref!.documentID)")
                    for addedgroupUser in self.addedTogroupUsers {
                        self.ref.collection("Users").document(addedgroupUser).updateData([
                                "groups": FieldValue.arrayUnion([groupref!.documentID])
                            ])
                    }
                }
            }
                print("groupName is \(groupName) and addedTogroup are \(self.addedTogroupUsers)")
        }
    }

我正在尝试查看 AnyCancellable 是否可行,但由于我使用的是未来承诺的链式数组,因此我不确定如何实现它。请让我知道您将如何解决这个问题,以便数组确实被填充,因为文档确实存在并且方法调用中的打印工作但 createGroup 函数中的 groupMates 数组随后打印一个空数组。谢谢!

编辑:添加 AnyCancallable 到代码以及建议的完成处理程序

工作犬

处理异步函数可能很棘手。您在 loadUserFromFirebase 中得到一个空数组,因为您返回得太早。使用旧式闭包尝试这种方法(未经测试):

func loadUserFromFirebase(groupUserIds: [String], handler: @escaping ([groupMate]) -> Void) { // <-- here
        var groupmateID = 0
        var groupMates : [String] = []
        print("groupUserIds: \(groupUserIds)" )
        
        for groupUserUID in groupUserIds {
            print("groupUserUID: \(groupUserUID)" )
            
            let future = Future<groupMate, Never> { promise in
                self.ref.collection("Users").document(groupUserUID).getDocument(){ (friendDocument, err) in
                    if let err = err {
                            print("Error getting documents \(err)")
                    } else {
                        print("friendDocument: \(String(describing: friendDocument?.data()))" )
                        
                        let groupUsername = (friendDocument?.data()?["username"]) as! String
                        let groupUID = (friendDocument?.data()?["uid"]) as! String
                        let groupName = (friendDocument?.data()?["name"]) as! String
                        let groupPic = (friendDocument?.data()?["imageurl"]) as! String
                        
                        promise(.success(groupMate(id: groupmateID, uid: groupUID , name: groupName , username: groupUsername, pic: groupPic)))
                    }
                    groupmateID += 1
                }
            }
            
            future.sink(receiveCompletion: { completion in
                print("in receiveCompletion")
                print(1, completion)
                switch completion {
                case .failure(let error):
                    print(3, error)
                    handler([])  // <-- here
                    return          // <-- here
                case .finished:
                    break
                }
            },
            receiveValue: {
                print("in receiveValue")
                groupMates.append($0)
                print(groupMates)
                handler(groupMates)  // <-- here
            })
        }
        // <-- do not return here
    }

   
    func creategroup(groupName: String) {
        addedTogroupUsers.append(self.uid)
        
        // -- here wait until you get the data
        loadUserFromFirebase(groupUserIds: addedTogroupUsers) { groupMates in
            
            let groupData: [String: Any] = [
                "groupName": "\(groupName)",
                "groupmates": groupMates      // <-- here
            ]
            
            print("groupMates are \(self.groupMates)")
            
            var groupref: DocumentReference? = nil
            groupref = ref.collection("groups").addDocument(data: groupData) { err in
                if let err = err {
                    print("Error adding document: \(err)")
                } else {
                    print("Document added with ID: \(groupref!.documentID)")
                    for addedgroupUser in self.addedTogroupUsers {
                        self.ref.collection("Users").document(addedgroupUser).updateData([
                            "groups": FieldValue.arrayUnion([groupref!.documentID])
                        ])
                    }
                }
            }
            print("groupName is \(groupName) and addedTogroup are \(addedTogroupUsers)")
        }
        
    }

请注意,如果您的目标是 ios 15、macos 12,那么使用 swift 5.5 async/await/task 功能会更好地服务。他们真的很好用。

编辑:尝试返回所有结果

func loadUserFromFirebase(groupUserIds: [String], handler: @escaping ([groupMate]) -> Void) {
    var groupmateID = 0
    var groupMates : [String] = []
    print("groupUserIds: \(groupUserIds)" )
    
    var arr: [Future<groupMate, Never>] = [Future<groupMate, Never>]()
    
    var cancellable = Set<AnyCancellable>()
    
    for groupUserUID in groupUserIds {
        print("groupUserUID: \(groupUserUID)" )
        
        let future = Future<groupMate, Never> { promise in
            self.ref.collection("Users").document(groupUserUID).getDocument(){ (friendDocument, err) in
                if let err = err {
                    print("Error getting documents \(err)")
                } else {
                    print("friendDocument: \(String(describing: friendDocument?.data()))" )
                    
                    let groupUsername = (friendDocument?.data()?["username"]) as! String
                    let groupUID = (friendDocument?.data()?["uid"]) as! String
                    let groupName = (friendDocument?.data()?["name"]) as! String
                    let groupPic = (friendDocument?.data()?["imageurl"]) as! String
                    
                    promise(.success(groupMate(id: groupmateID, uid: groupUID , name: groupName , username: groupUsername, pic: groupPic)))
                }
                groupmateID += 1
            }
        }
        arr.append(future)
    }
    
    Publishers.MergeMany(arr)
        .collect()
        .sink { _ in
            print("-----> merging ")
        } receiveValue: { value in
            print("-----> value: \(value)")
            groupMates = value  // <--- maybe append?
            print(groupMates)
            handler(groupMates)
        }
        .store(in: &cancellable)
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章