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

Posted

技术标签:

【中文标题】如何防止 Swift 3 中的嵌套完成块?【英文标题】:How can I prevent nested completion blocks in Swift 3? 【发布时间】:2017-06-01 07:42:39 【问题描述】:

我在下面提供的代码中有一系列嵌套的完成块。这是因为我需要在后台发出单独的网络请求以抽象数据以用于下一个方法,该方法提供另一个完成块,依此类推。有没有办法解决?非常感谢任何提示!

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)
            )
        )
    )
 

【问题讨论】:

它不会改变你正在做的事情的逻辑 - 但它可以通过从完成处理程序中对下一步进行函数调用来使其更具可读性,并单独拥有代码 你也可以查看 PromiseKit 看到这个答案***.com/a/44092277/1825618 感谢大家的帮助和资源! 您还可以使用 DispatchQueues 顺序运行您的网络请求。不过,我也推荐使用 PromiseKit,一旦你掌握了它,它比任何内置的处理异步请求的方式都要强大和方便。 【参考方案1】:

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

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 函数以接受完成块并默认为不执行任何操作的块,而不是使用可选块。感觉干净多了。

【讨论】:

【参考方案2】:

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

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
    

【讨论】:

以上是关于如何防止 Swift 3 中的嵌套完成块?的主要内容,如果未能解决你的问题,请参考以下文章

如何在swift 5中的完成块内向用户显示警报

如何将 Objective-C 的完成块转换为 Swift?

如何在 Swift 中转义完成块以返回正常的应用程序流程?

如何表示 nil Error Swift 完成块

如何防止意外触摸触发 swift 4.2 中的 touchesBegan?

Swift:如何将从委托接收到的值传递给函数的完成块?