ios 如何在Swift 4中进行两个并发API调用

omvjsjqw  于 2023-08-08  发布在  iOS
关注(0)|答案(3)|浏览(127)

感谢帮助提前,我有两个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"

字符串

svdrlsy4

svdrlsy41#

这正是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
    }
}

字符串

uubf1zoe

uubf1zoe2#

我会使用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

lymgl2op

lymgl2op3#

调度组在一种情况下可能会失败,假设第一个API响应在进入第二个组之前返回。因此,在这种情况下,您的通知块将在没有第二个API的情况下被调用。所以为了防止这个问题,你必须在任何API调用之前添加所有的enters语句。就像-

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.
    }
}

字符串

相关问题