本文主要目的是简单介绍三种异步加载图片的方法,核心在异步
一般 app 开发都是用第三方库如 SDWebImage
因为是从网上下载图片,而如果网速不太OK的话,下载的时候UI界面会卡住(方法阻塞在这里,下面的代码没法执行)
所以不能在主线程里下载图片。下面介绍3种方法,在新开的线程中下载。
假设 现在我在ViewController里添加了一个button,一个UIImageView 名字 imgView 。给button加了一个click1点击事件。
// button的点击事件
func click1(){
// 方法一,新线程
let thread = Thread(target: self, selector: #selector(download), object: nil)
// thread 执行的方法 download() 在后面
thread.start()
}
// 下载事件. 把下载的相关代码封装在这里
func download() {
let url = URL(string: "https://avatar.csdn.net/0/2/9/1_m0_38076563.jpg")
// 新建一个URL(这个URL里是个图片)
let data = Data(contentsOf: url!)
let img = UIImage(data: data! )
imgView?.performSelector(onMainThread: Selector("setImage:"), with: img!, waitUntilDone: false)
// 在主线程里更新 img,下面是更常用的办法
}
// 第二个办法,队列(GCD)
队列存放任务,GCD 会自动将队列中的任务取出,放到合适的线程中执行
任务就是 一个 block,代码片段
队列有两种: 并发队列和串行队列
1. 串行队列: 任务一个接一个的执行,上一个任务执行不完,下一个永远就没有机会去执行(单线程)
2. 并行队列: 允许多个任务同时执行(队列内有多个线程)
func click(){
let gcd_queue = DispatchQueue(label: "Test") // 新起一个队列
//synchronize:同步,asynchronize:异步
gcd_queue.async() { // 队列内安排一个任务:
let url = URL(string: "https://avatar.csdn.net/0/2/9/1_m0_38076563.jpg")
let data = Data(contentsOf: url!)
let img = UIImage(data: data! )
DispatchQueue.main.async(execute: { // 在主线程更新 UI,因此向主线程所在的队列提交一个任务:
self.imgView.image = img
})
}
// 第三个方法,OperationQueue,只需要提交任务就行了
func click(){
// 队列里添加操作:
OperationQueue().addOperation {
let url = URL(string:"https://avatar.csdn.net/0/2/9/1_m0_38076563.jpg")
let data = NSData(contentsOf: url!)
let img = UIImage(data: data!asData)
self.imgView.performSelector(onMainThread: Selector("setImage:"), with: img!, waitUntilDone: false)
}
// 可以设置队列的 maxConcurrentOperationCount = 3 // 允许最大并发操作数
}