iOS多线程

首页 / iOS / 正文

多线程

在之前我们提到,整个列表的数据都是从网络中请求加载到cell当中的,但是由于cell中含有图像的加载的问题,会造成我们App的启动速度十分缓慢和我们在滑动列表的时候产生严重的卡顿,所以接下来我们需要利用线程对列表的滑动体验进行优化。

优化前的效果

before.gif

线程是什么

线程是某一进程中一个单独运行的程序。也就是进程的一个实体,是CPU调度和分派的基本单位。

我们如何使用线程

在iOS中,线程通常被分为主线程和其他线程。通常我们编写的代码都是在主线程中运行的。为了优化体验,我们需要将图片的加载过程放入到其他线程中,并且在Cell中使用占位图,在非主线程中请求图片数据并加载到Cell上。

let downloadImageThread = Thread(block: { [self] in
            do {
                
                rightImage.image = UIImage(data: try Data(contentsOf: URL(string: model.thumbnail_pic_s)!))
            } catch {
                
            }
        })
        downloadImageThread.name = "downloadImageThread"
        downloadImageThread.start()

在写下以上代码之后,可以发现无论是App的启动速度和列表的滑动体验都又了明显的提升。

效果如下

after.gif

但是我们可以在Xcode中看见系统进行了警告warn.png

虽然我们提前放置了占位图,但是任何有关UI的操作都应该放在主线程中进行

所以我们在这里引入另外一个线程的管理方式

Grand Central Dispatch(GCD)

在了解GCD之前,我们需要在这里引入两个概念,任务队列

  • 任务:指的是我们需要执行的操作,也就是代码块(block)中的代码。
  • 队列:指的是执行任务的等待队列,从数据结构中我们知道队列的特点是先进先出,所以我们的任务也是先进先出的。
GCD的优点就是,使开发者从面向线程较为底层的管理变成了面向队列,由系统来为队列从线程池中分配线程执行我们的任务。

将上述代码改成使用GCD的方式则如下所示

//全局并发队列
let downloadQueue = DispatchQueue.global(qos: .default)
        let mainQueue = DispatchQueue.main
        //在非主队列中进行网络请求
        downloadQueue.async(execute: { [self] in
            var modelImage: UIImage? = nil
            do {
                 modelImage = UIImage(data: try Data(contentsOf: URL(string: model.thumbnail_pic_s)!))
            } catch {

            }
            //在主队列中进行UI操作
            mainQueue.async(execute: { [self] in
                rightImage.image = modelImage
            })
        })

最终效果

aafter.gif

评论区
头像
文章目录