一、概述
我们在实际开发过程中,一个页面可能需要请求多个接口,最后等到所有接口数据都请求完成后,再执行创建 UI
的操作。这个时候就需要用到调度组了。它可以并发执行多个网络请求,不会阻塞主线程,造成卡顿现象,并且监听到啥时候请求都执行完毕。
二、在 OC
中的写法
- (void)requestDatasGroup {
// 创建调度组
dispatch_group_t group = dispatch_group_create();
// 创建队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 模拟异步发送网络请求 A
// 入组
dispatch_group_enter(group);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"接口 A 数据请求完成");
// 出组
dispatch_group_leave(group);
});
// 模拟异步发送网络请求 B
// 入组
dispatch_group_enter(group);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"接口 B 数据请求完成");
// 出组
dispatch_group_leave(group);
});
NSLog(@"我是最开始执行的,异步操作里的打印是后执行的");
// 调度组的任务都执行完毕
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"接口 A 和接口 B 的数据请求都已经完毕!, 开始合并两个接口的数据");
});
}
三、在 Swift 4.0
中的写法
/// 网络请求调度组
private func datasRequestGroup() {
// 创建调度组
let workingGroup = DispatchGroup()
// 创建多列
let workingQueue = DispatchQueue(label: "request_queue")
// 模拟异步发送网络请求 A
// 入组
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口 A 数据请求完成")
// 出组
workingGroup.leave()
}
// 模拟异步发送网络请求 B
// 入组
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口 B 数据请求完成")
// 出组
workingGroup.leave()
}
print("我是最开始执行的,异步操作里的打印后执行")
// 调度组里的任务都执行完毕
workingGroup.notify(queue: workingQueue) {
print("接口 A 和接口 B 的数据请求都已经完毕!, 开始合并两个接口的数据")
}
}
四、注意事项
- 如果调度组
group
中没有任务,会直接执行dispatch_group_notify
方法- 入组
dispatch_group_enter
、 出组dispatch_group_leave
必须成对出现- 当入组多于出组,
dispatch_group_notify
方法永远不会执行- 当出组多于入组,会崩溃