免费开源的iOS开发学习平台

GCD使用介绍:4-队列组dispatch group

在使用GCD进行任务操作时,有时会希望若干个任务执行之间有先后执行的依赖关系,例如,当A、B两个异步任务完成后,再去完成C任务,这时就可以使用队列组dispatch group来完成。

队列组基本介绍

在串行队列中,任务是按照进入队列的顺序依次执行,因此任务和任务之间是有明确的先后顺序的。但是对于并行队列的任务来说,由于任务会被自动分配到不同的线程中执行,因此任务完成的顺序是不确定的。假如希望给并行队列中的任务设置执行顺序,例如,当任务A和任务B完成后,再去完成任务C,就需要使用到任务组dispatch group。

在GCD中,苹果官方为我们提供了如下一些有关队列组操作的函数。

  • 创建队列组
dispatch_group_t dispatch_group_create( void);
  • 向队列组中插入一个异步任务
void dispatch_group_async( dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block); 
  • 队列组中其他任务执行完成后,执行的任务,通常可以用来设置UI界面
void dispatch_group_notify( dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block); 

示例代码

在下方的示例代码中,点击一个按钮,会启动两个异步下载任务,下载图片完成后,会更新屏幕上的UIImageView。等两个下载任务都完成后,更新界面上的下载任务状态Label。

  • 使用StroyBoard创建界面,并添加连线。
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *task1ImageView;
@property (weak, nonatomic) IBOutlet UIImageView *task2ImageView;
@property (weak, nonatomic) IBOutlet UILabel *taskLabel;
@end
  • 【开始下载】按钮点击的实现方法如下
- (IBAction)startTask:(id)sender {  
    NSLog(@"0--%@", [NSThread currentThread]);
    //创建队列组
    dispatch_group_t group = dispatch_group_create(); 
    //创建并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    
    //创建队列组中的第一个异步任务
    dispatch_group_async(group, queue, ^{
        NSLog(@"1.1--%@", [NSThread currentThread]);
        //下载网络图片
        NSString *urlStr = @"http://qiniu.99ios.com/99logo.png";
        NSURL *url = [NSURL URLWithString:urlStr];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:imageData];       
        //返回主队列设置图片
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"1.2--%@", [NSThread currentThread]);
            self.task1ImageView.image = image;
        });
    });   
    //创建队列组中的第二个异步任务
    dispatch_group_async(group, queue, ^{
       NSLog(@"2.1--%@", [NSThread currentThread]);
        //下载网络图片
        NSString *urlStr = @"http://qiniu.99ios.com/99logo.png";
        NSURL *url = [NSURL URLWithString:urlStr];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:imageData];        
        //返回主队列设置图片
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"2.2--%@", [NSThread currentThread]);
            self.task2ImageView.image = image;
        });       
    });    
    //任务组中的任务完成后,执行的动作
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"3--%@", [NSThread currentThread]);
       self.taskLabel.text = @"下载完成";
    });  
}

运行结果如下。我们可以看到,队列组中的异步任务执行会在另外的进程中执行,等所有的任务都执行完成后,会通知执行dispatch_group_notify()中的任务。

示例代码

https://github.com/99ios/11.2.4