DispatchQueue.main.async 阻塞主线程
Posted
技术标签:
【中文标题】DispatchQueue.main.async 阻塞主线程【英文标题】:DispatchQueue.main.async blocking the main thread 【发布时间】:2018-11-03 04:32:56 【问题描述】:我一直在尝试在 Swift 3.0 中创建照片库,并且我想将存储在文档目录中的图像异步加载到集合视图中。我试过DispatchQueue.main.async
,但它阻塞了主线程并冻结了应用程序几秒钟:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let identifier = "ImageCell"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! ImageCell
let url = self.imageURL[indexPath.row]
cell.lazyLoadImage(from: url)
return cell
还有 ImageCell 类:
class ImageCell: UICollectionViewCell
@IBOutlet weak var imageView: UIImageView!
func lazyLoadImage(from url: URL)
DispatchQueue.main.async
if let image = UIImage(contentsOfFile: url.path)
self.imageView.image = image
感谢您的帮助。谢谢。
【问题讨论】:
如果您在应用程序冻结时暂停应用程序,主线程的回溯中是什么? 其实你什么都没做我的意思是你在主线程中,并且在主线程中调度块 如果图像只是文件,我不会认为您需要异步发送任何东西;只需加载图像。如果您的图像文件非常大,请考虑在单元格中加载更快的缩略图。 【参考方案1】:先切换到后台线程加载图片,再切换到主线程显示图片。
func lazyLoadImage(from url: URL)
DispatchQueue.global(qos: .userInteractive).async
if let image = UIImage(contentsOfFile: url.path)
DispatchQueue.main.async
self.imageView.image = image
【讨论】:
你还需要取消之前的任务(如果正在运行)【参考方案2】:你做错了。简而言之,我可以说这不是“延迟加载”。您正在做的是阻止线程从URL
下载内容并将其加载到UIImageView
。在下载发生并且您在“可重用单元”中使用它之前,该线程不会被释放,很明显您的应用程序会卡住!
解决方案
有许多最受欢迎的库,例如 AlamofireImage、SDWebImage、Kingfisher。我从中获取“SDWebImage”,您可以通过以下代码以async
方式调用加载图像:
imageView.sd_setImage(with: url , placeholderImage: nil)
另外,请参阅此 SO 问题 (how to implement lazy loading of images in table view using swift) 了解更多详情。
【讨论】:
以上是关于DispatchQueue.main.async 阻塞主线程的主要内容,如果未能解决你的问题,请参考以下文章
为啥 DispatchQueue.main.async 会影响单元格自动调整大小?
SwiftUI - HealthKit 中的 DispatchQueue.main.async
SwiftUI - HealthKit 中的 DispatchQueue.main.async
Swift 5:我无法让我的 UITableView 及时更新(同时使用 `DispatchQueue.global().sync` 和 `DispatchQueue.main.async`