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

GCD使用介绍:3-线程间通信

由于UI的更新和操作是由主线程负责的,因此,当使用子线程获取到数据时(例如通过网络获取得到了服务器返回的数据),需要返回主线程对UI界面进行更新,这时就涉及到线程间的通信。

线程间通信简介

在涉及网络数据获取的过程中,一般会使用异步任务+并发队列进行数据获取,当获取到网络服务器返回的数据后,需要在主线程中把数据显示在屏幕上,因此这就涉及到线程间的通信。在并行队列中的任务,还可以嵌套子任务,嵌套的子任务可以设置为在主线程中执行的任务。

示例代码

下方的示例代码模拟了一个从网络获取一张图片的数据,并在屏幕上显示在一个UIImageView控件上的过程。在这个案例中,设置一个网络下载的异步任务,并放在并行队列中执行,此时,GCD会在一个新的线程中执行下载任务,当网络图片下载完成后,由于涉及到更新UI,所以必须嵌套一个子任务在主队列中执行。

  • 由于涉及到发送网络请求,需要提前在info.plist文件中设置App Transport Security Settings参数。

  • 搭建UI界面,添加一个UIImageView以及一个UIButton,并连线;

  • 在按钮的点击方法中,在异步任务+并行队列中实现网络图片的下载操作,并嵌套一个子任务在主线程中更新界面。

- (IBAction)downLoadImageView:(id)sender {
    //获取并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NSLog(@"0---%@", [NSThread currentThread]);
    
    //异步任务
    dispatch_async(queue, ^{
        //从网络下载图片
        NSString *urlString = @"http://qiniu.99ios.com/99logo.png";
        NSURL *url = [NSURL URLWithString:urlString];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:imageData];
        NSLog(@"1---%@", [NSThread currentThread]);
 
        //返回主线程设置UI
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
            NSLog(@"2---%@", [NSThread currentThread]);
        });
        
    });
    
    NSLog(@"3---%@", [NSThread currentThread]);
}

运行结果如下。通过日志打印的顺序可以看出程序执行的顺序,即:网络下载任务是在新的线程中执行的,并且图片下载完毕后,回到主线程设置图片显示。

示例代码

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