预先感谢您的帮助, 我有两个 API 调用,都是并发的,任何调用都可以先成功(我不想按顺序调用),在两个调用成功后,我必须停止我的活动指示器并重新加载我的 tableView, 这是我的代码,但我不知道这是正确的方法,也不知道如何重新加载我的 tableView 并停止我的活动指示器。
func downloadDetails(){
let operationQueue: OperationQueue = OperationQueue()
let operation1 = BlockOperation() {
WebServiceManager.getAData(format:A, withCompletion: {(data: Any? , error: Error?) -> Void in
if let success = data {
DispatchQueue.main.async {
(success code)
}
}
})
let operation2 = BlockOperation() {
webServiceManager.getBData(format: B, withCompletion: {(data: Any? , error: Error?) -> Void in
if let success = data {
DispatchQueue.main.async {
(success code)
}
}
})
}
operationQueue.addOperation(operation2)
}
operationQueue.addOperation(operation1)
}
downloadDetails() "calling function"
这正是
DispatchGroup
的用例。输入每个呼叫的组,在呼叫结束时离开组,并添加一个通知处理程序以在呼叫完成时触发。不需要单独的操作队列;这些已经是异步操作了。
func downloadDetails(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter() // <<---
WebServiceManager.getAData(format:A, withCompletion: {(data: Any? , error: Error?) -> Void in
if let success = data {
DispatchQueue.main.async {
(success code)
dispatchGroup.leave() // <<----
}
}
})
dispatchGroup.enter() // <<---
webServiceManager.getBData(format: B, withCompletion: {(data: Any? , error: Error?) -> Void in
if let success = data {
DispatchQueue.main.async {
(success code)
dispatchGroup.leave() // <<----
}
}
})
dispatchGroup.notify(queue: .main) {
// whatever you want to do when both are done
}
}
我会使用OperationQueue。
它是长时间运行任务的首选,并让您可以根据需要控制取消请求。
在每个操作结束时,您可以检查操作计数以了解剩余的操作。
我添加了伪代码。
let operationQueue: OperationQueue = OperationQueue()
func downloadDetails(){
let operation1 = BlockOperation() { [weak self] in
guard let strongSelf = self else {
return
}
sleep(2)
DispatchQueue.main.async {
strongSelf.handleResponse()
}
let operation2 = BlockOperation() { [weak self] in
guard let strongSelf = self else {
return
}
sleep(2)
DispatchQueue.main.async {
strongSelf.handleResponse()
}
}
strongSelf.operationQueue.addOperation(operation2)
}
self.operationQueue.addOperation(operation1)
}
func handleResponse() {
print("OPERATIONS IN PROGRESS: \(self.operationQueue.operations.count)")
if self.operationQueue.operations.count == 0 {
print("ALL OPERATIONS ARE COMPLETE")
}
}
func cancelOperation() {
self.operationQueue.cancelAllOperations()
}
此打印
OPERATIONS IN PROGRESS: 1
OPERATIONS IN PROGRESS: 0
ALL OPERATIONS ARE COMPLETE
在一种情况下,调度组可能会失败,假设第一个 api 响应在进入第二个组之前返回。因此,在这种情况下,您的通知块将在没有第二个 api 的情况下被调用。因此,为了防止出现该问题,您必须在任何 api 调用之前添加所有 Enter 语句。喜欢-
func download(){
let dispatchGroup = DispatchGroup()
/// Enter into the group for all the apis from here only.
dispatchGroup.enter()
dispatchGroup.enter()
ApiManager.shared.data(request: firstRequest, withCompletion: {(data: Any? , error: Error?) -> Void in
dispatchGroup.leave()
})
ApiManager.shared.data(request: secondRequest, withCompletion: {(data: Any? , error: Error?) -> Void in
dispatchGroup.leave()
})
dispatchGroup.notify(queue: .main) {
/// From here you may notify to hide indicator and reload the table.
}
}