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

2017-12-03  本文已影响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或者其他的操作。完美!

上一篇下一篇

猜你喜欢

热点阅读