Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何防止Swift 3中嵌套的完成块?_Swift_Nested_Completionhandler - Fatal编程技术网

如何防止Swift 3中嵌套的完成块?

如何防止Swift 3中嵌套的完成块?,swift,nested,completionhandler,Swift,Nested,Completionhandler,我在下面提供的代码中有一系列嵌套的完成块。这是因为我需要在后台发出单独的网络请求来提取数据,以便在下一个方法中使用,该方法提供了另一个完成块,依此类推。这有什么办法吗?任何提示都非常感谢 func fetchNearbyUsers(forCurrentUser user: User, completionHandler: usersCompletionHandler?) { self.fetchAllUsers(completionHandler: { (users: [User])

我在下面提供的代码中有一系列嵌套的完成块。这是因为我需要在后台发出单独的网络请求来提取数据,以便在下一个方法中使用,该方法提供了另一个完成块,依此类推。这有什么办法吗?任何提示都非常感谢

func fetchNearbyUsers(forCurrentUser user: User, completionHandler: usersCompletionHandler?) {

    self.fetchAllUsers(completionHandler: { (users: [User]) in

        ChatProvider.sharedInstance.fetchAllChatrooms(completionHandler: { (chatrooms: [Chatroom]) in

            self.validateNewUsers(currentUser: user, users: users, chatrooms: chatrooms, completionHandler: { (validUsers: [User]) in

                guard validUsers.isEmpty == false else {
                    completionHandler?([])
                    return
                }
                completionHandler?(validUsers)
            })
        })
    })
} 

为什么不调用一个函数并使用一些布尔值来确保两者都是完整的呢。这里有一些伪代码

var completeA = false
var completeB = false

func doStuff {

    asyncStuffA(stuff {

        asyncStuffB(stuff {

            }, completion: {

                completeB = true
                completionHandler()

        })

        }, completion: {

            completeA = true
            completionHandler()

    })
}


func completionHandler() {
    if completeA && completeB {
        // Both are complete
        completeA = false
        completeB = false
    }
}

这里的一个选项是使用高阶工厂函数(即返回其他函数的函数)将块分解为它们自己的函数

func fetchNearbyUsers(forCurrentUser user: User, completionHandler: @escaping usersCompletionHandler = { _ in }) {      
    self.fetchAllUsers(completionHandler: self.allUsersFromChatrooms(user: user, completionHandler: completionHandler))
}

func allUsersFromChatrooms(user: User, completionHandler: @escaping usersCompletionHandler) -> ([User]) -> Void {
    return { users in
        ChatProvider.sharedInstance.fetchAllChatrooms(completionHandler: self.validatedUsersInChatrooms(user: user, users: users, completionHandler: completionHandler))
    }
}

func validatedUsersInChatrooms(user: User, users: [User], completionHandler: @escaping usersCompletionHandler) -> ([Chatroom]) -> Void {
    return { chatrooms in
        self.validateNewUsers(currentUser: user, users: users, chatrooms: chatrooms, completionHandler: completionHandler)
    }
}
在上面的代码中,
validatedUsersInChatrooms
将返回一个函数,该函数接受聊天室数组,并使用已验证的用户调用提供的完成处理程序。函数
allUsersFromChatrooms
返回一个函数,该函数接受一组用户,然后获取聊天室,并使用聊天室中经过验证的用户数组调用提供的完成处理程序


还请注意,我将
fetchNearbyUsers
函数更改为接受一个完成块,并默认为一个不执行任何操作的块,而不是使用可选块。它让我感觉更干净。

它不会改变你正在做的事情的逻辑-但是它可以变得更可读,只需从完成处理程序调用一个函数到下一步,并单独使用代码。你也可以查看PromiseKit看到这个答案谢谢大家的帮助和资源!您还可以使用DispatchQueues按顺序运行网络请求。不过,我也建议您使用PromiseKit,一旦掌握了窍门,它比任何内置的处理异步请求的方法都更加强大和方便。