iOS如何实现“多个异步操作结束后执行后续动作”

如何实现多个异步操作结束后执行后续动作

场景:我们可能对列表中的数据进行批量操作后,执行下一步操作。如多选删除后,刷新页面;如多选下载后,提示下载完成。

我们需要用到的一个核心的东西就是信号量:DispatchSemaphore


首先介绍下信号量的基本语法
初始化

swift

let sema = DispatchSemaphore.init(value: 0)

oc

dispatch_semaphore_t sema = dispatch_semaphore_create(0);

可以看出,我们传了一个 Int 值用于初始化信号量。

两个核心方法

swift

//等待
sema.wait()
//完成
sema.signal()

oc

//等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//完成
dispatch_semaphore_signal(sema);

wait会对信号量 -1-1后,如果信号量<0,则会阻塞线程
signal会对信号量 +1


接着让我们看下信号量的简单用法
1、单任务实例

以 swift 为例

//1
DispatchQueue.global().async {
    //2
    let sema = DispatchSemaphore.init(value: 0)
    //3
    NetManager.shared().checkPermission(withSpace: model.spaceType, andParentID: parentId, andChildenID: [modid], andAction: "copyFile2All", success: { (result) in
        //4
        sema.signal()
     }) { (msg) in
        //4
        sema.signal()
    }
    //5
    sema.wait()
    //6
}           

代码解读:

  1. wait 方法会阻塞主线程,所以需要放在子线程中,本例放在 global 中
  2. 创建信号量对象,信号量为 0
  3. 网络请求的任务,使用的是AFNetworking
  4. 任务完成,信号量+1
  5. 信号量首先-1,然后检测信号的值。当信号量<0时阻塞,并一直检测信号量变化,直到信号量>0时,便会往后执行,
  • 注意:使用信号量,一定要放在子线程中,否则主线程会一直阻塞。

如上所示,我们可以在 注释6的位置写上我们需要执行的代码。便达到了通过信号量等待一个任务完成后,执行下一个任务的要求。

2、多任务实例
DispatchQueue.global().async {
    let sema = DispatchSemaphore.init(value: 0)
    for i in self.selectedItems {
        NetManager.shared().checkPermission(withSpace: model.spaceType, andParentID: parentId, andChildenID: [modid], andAction: "copyFile2All", success: { (result) in
            self.performSegue(withIdentifier: "showDirectoryTreevcID", sender: "copy")
            sema.signal()
        }) { (msg) in
            //
            sema.signal()
        }
    }
    for _ in self.selectedItems {
        sema.wait()
    }
    //刷新 UI 等操作可以放在这里(注:如果是对 UI 操作要放在主线程哦)
    
}

通过单任务实例理解这个多任务的实例应该不难,在此不多做赘述。


总结
  • 上例中的网络请求方法只是实例用的,读者可以自己写个网络请求替换掉
  • 信号量有三个比较关键的点(信号量的值,wait 方法,signal 方法),理解透了用起来很简单,且好用
  • 信号量的初始化的值在本例中为 0,如果是正整数,一般用于多任务线程池(比如同时最大支持n 个任务上传)。

你可能感兴趣的:(iOS如何实现“多个异步操作结束后执行后续动作”)