Ios 嵌套的完成块是否是不良设计的标志?

Ios 嵌套的完成块是否是不良设计的标志?,ios,swift,oop,asynchronous,completionhandler,Ios,Swift,Oop,Asynchronous,Completionhandler,我有一个方法调用三个函数,每个函数向Firebase发出请求,并在完成处理程序中传回数据。一旦来自两个完成处理程序的数据被发回,我调用另一个方法来传入数据并发回一个有效的结果。像这样的嵌套块是设计拙劣的标志吗 func fetchNearbyUsers(for user: User, completionHandler: usersCompletionHandler?) { self.fetchAllUsers(completionHandler: { (use

我有一个方法调用三个函数,每个函数向Firebase发出请求,并在完成处理程序中传回数据。一旦来自两个完成处理程序的数据被发回,我调用另一个方法来传入数据并发回一个有效的结果。像这样的嵌套块是设计拙劣的标志吗

    func fetchNearbyUsers(for 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)
                    })
                })
            })
        }
//其他方法

    func fetchAllUsers(completionHandler: usersCompletionHandler?) {

        var users: [User] = []

        let group = DispatchGroup()
        let serialQueue = DispatchQueue(label: "serialQueue")

        DatabaseProvider.sharedInstance.usersDatabaseReference.observe(.value, with: {
            snapshot in
            guard let data = snapshot.value as? [String: AnyObject] else { return }

            for (_, value) in data {

                guard let values = value as? [String: AnyObject] else { return }
                guard let newUser = User(data: values) else { return }
                group.enter()
                newUser.fetchProfileImage(completionHandler: { (image) in
                    serialQueue.async {
                        newUser.profileImage = image
                        users.append(newUser)
                        group.leave()
                    }
                })
            }

            group.notify(queue: .main, execute: {
                completionHandler?(users)
            })

        })

    }



    func fetchAllChatrooms (completionHandler: chatroomsHandler?)  {
        var chatrooms = [Chatroom]()
        let group = DispatchGroup()
        let serialQueue = DispatchQueue(label: "serialQueue")

        DatabaseProvider.sharedInstance.chatroomsDatabaseReference.observe(.value, with: { snapshot  in
            guard let data = snapshot.value as? [String: AnyObject] else { return }

            for (_, value) in data {
                guard let value = value as? [String: AnyObject] else { return }
                guard let newChatroom = Chatroom(data: value) else { return }

                group.enter()
                self.fetchChatroomUsers(chatroom: newChatroom, completionHandler: { (chatroom) in
                    serialQueue.async {
                        chatrooms.append(newChatroom)
                        group.leave()
                    }
                })
            }
            group.notify(queue: .main, execute: {
                completionHandler?(Array(Set<Chatroom>(chatrooms)))
            })
        })
    }


private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: usersCompletionHandler?) {
    let chatPartners = self.chatPartners(currentUser: currentUser, chatrooms: chatrooms)
    let validUsers = users
        .filter { currentUser.id != $0.id }
        .filter { currentUser.distanceFromUser(atLocation: $0.coordinates) <= 8046.72 }
        .filter { !chatPartners.contains($0.id) }
    completionHandler?(validUsers)
}

private func chatPartners (currentUser: User, chatrooms: [Chatroom]) -> Set<String> {
    var results = [String]()
    for chatroom in chatrooms {
        if currentUser.id == chatroom.firstUserId {
            results.append(chatroom.secondUserId)
        } else if currentUser.id == chatroom.secondUserId {
            results.append(chatroom.firstUserId)
        }
    }
    return Set(results)
}
func fetchAllUsers(completionHandler:usersCompletionHandler?){
变量用户:[用户]=[]
let group=DispatchGroup()
让serialQueue=DispatchQueue(标签:“serialQueue”)
DatabaseProvider.sharedInstance.usersDatabaseReference.observe(.value,带:{
快照
guard let data=snapshot.value as?[String:AnyObject]else{return}
对于数据中的(_,值){
guard let values=值为?[String:AnyObject]else{return}
guard let newUser=User(数据:值)else{return}
group.enter()
fetchProfileImage(completionHandler:{(图像)位于
serialQueue.async{
newUser.profileImage=image
users.append(newUser)
小组请假()
}
})
}
通知组(队列:.main,执行:{
completionHandler?(用户)
})
})
}
func fetchall聊天室(completionHandler:chatroomsHandler?){
var聊天室=[Chatroom]()
let group=DispatchGroup()
让serialQueue=DispatchQueue(标签:“serialQueue”)
DatabaseProvider.sharedInstance.chatroomsDatabaseReference.observe(.value,带:{snapshot in
guard let data=snapshot.value as?[String:AnyObject]else{return}
对于数据中的(_,值){
guard let value=值为?[String:AnyObject]else{return}
guard let newChatroom=聊天室(数据:值)else{return}
group.enter()
self.fetchChatroomUsers(聊天室:newChatroom,completionHandler:{(聊天室)在
serialQueue.async{
聊天室。附加(新聊天室)
小组请假()
}
})
}
通知组(队列:.main,执行:{
completionHandler?(数组(集合(聊天室)))
})
})
}
private func validateNewUsers(当前用户:用户,用户:[用户],聊天室:[聊天室],completionHandler:usersCompletionHandler?){
让chatPartners=self.chatPartners(当前用户:当前用户,聊天室:聊天室)
让validUsers=用户
.filter{currentUser.id!=$0.id}
.filter{currentUser.distanceFromUser(atLocation:$0.coordinates)集合{
变量结果=[String]()
聊天室中的聊天室{
如果currentUser.id==chatroom.firstUserId{
results.append(chatroom.secondUserId)
}如果currentUser.id==chatroom.secondUserId,则为else{
results.append(chatroom.firstUserId)
}
}
返回集(结果)
}

不一定,但除非它们非常简单,否则它们应该是作为参数传递的专用方法。复杂的嵌套闭包很难推理,也很难调试,因此我们强烈反对在实践中使用它。@Joshatternerry,我想我的方法对于嵌套闭包来说太复杂了。关于w如果您愿意进行重构,我将不胜感激。我正在努力在编写干净的代码和使事情正常运行之间找到平衡。有一个专门的SE页面用于代码审查:。虽然您的问题似乎在这里,但您可能也会在那里得到很好的见解。