美文网首页
如何知道iOS多个异步任务执行完成的回调通知

如何知道iOS多个异步任务执行完成的回调通知

作者: 轰炸机上调鸡尾酒 | 来源:发表于2017-12-03 19:13 被阅读16次

    项目遇到一个问题,一个页面有两个接口,需要知道两个网络请求都成功后再去更新UI。网络请求是异步的,如何检测两个网络请求都请求结束呢。
    这个时候信号量就派上用场了。

    信号量是一种计数器,如果方法中设置了一个信号量,当它大于0,方法会按正常模式往下执行,如果等于0则会阻塞住,直到它大于0时,就会往下执行了。

    ////创建一个信号量,初始值为0
    let semaphore = DispatchSemaphore.init(value: 0)
    //等待信号,信号量减1,如果信号量小于0,方法会阻塞住。
    semaphore.wait()
    //发送一个信号,信号量加1
    semaphore.signal()
    

    DispatchSemaphore.init(value: 0)传入的参数为lnt,输出一个DispatchSemaphore的对象。值得注意的是,这里的传入的参数value必须大于或等于0。

    semaphore.wait()这个函数会使传入的信号量的值减1。这个函数的作用是这样的,如果信号量的值大于0,该函数所处线程就继续执行下面的语句,并且将信号量的值减1;如果信号量的值为0,那么这个函数就阻塞当前线程等待timeout。

    好了开始进入正题,如果在多个网络请求完成后得到这个消息的回调。信号量在这里就立功了。当然我们还要结合使用下线程组。
    注意因为网络请求是异步的。线程组里任务需要提前进入我们创建的并行队列中。

       override func viewDidLoad() {
            super.viewDidLoad()
            fetchPreInfo()
            isShowDraftView()
            //用全局队列来接受线程组的任务回调
            let defaultQueue = DispatchQueue.global()
            group.notify(queue: defaultQueue) {
                   print("Done")
             }
       }
        fileprivate let group = DispatchGroup()
        fileprivate let queue = DispatchQueue(label: "create.diary", attributes: .concurrent)
    
    // MARK: - 这个方法是请求是否展示草稿
        func isShowDraftView() {
            //将任务1异步提交到queue中
            queue.async(group: group) {
                //对于这个异步的网络请求任务1,我们使用信号量使其同步化
                let semaphore =  DispatchSemaphore(value: 0)
                self.hasDraftView(["type": "1", "diary_id": String(self.diaryId)]) { [weak self](hasDraft, error, _) in
                   //网络请求有结果之后(无论成功还是失败)信号量+1,标识这任务1已经完成
                    semaphore.signal()
                    print("是否展示草稿接口请求完成")
                }
               //这里wait函数设置下超时等待时间,如果超过30秒,我们认为网络请求超时失败了。
                _ = semaphore.wait(timeout: DispatchTime.now() + 30)
            }
        }
        
        // MARK: - 这个方法获取发日记贴前的预置信息
        func fetchPreInfo() {
            //将任务2异步提交到queue中
            queue.async(group: group) {
                //对于这个异步的网络请求任务2,我们也使用信号量使其同步化
                let semaphore =  DispatchSemaphore(value: 0)
                self.viewModel.fetchPreInfo (["diary_id": self.diaryId]) { [weak self] (data, error, _) in
                 //网络请求有结果之后(无论成功还是失败)信号量+1,标识这任务1已经完成
                    semaphore.signal()
                    print("获取发日记贴前的预置信接口请求完成")
                }
                // 在网络请求任务成功之前,信号量等待中
                _ = semaphore.wait(timeout: DispatchTime.now() + 30)
            }
        }
        
    

    这样我们就可以检测到两个任务都完成之后,然后回到主线程做一个UI或者其他的操作。完美!

    相关文章

      网友评论

          本文标题:如何知道iOS多个异步任务执行完成的回调通知

          本文链接:https://www.haomeiwen.com/subject/zfnwbxtx.html