【问题标题】:DispatchQueue.main.async blocking the main threadDispatchQueue.main.async 阻塞主线程
【发布时间】: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
            }
        }
    }
}

感谢您的帮助。谢谢。

【问题讨论】:

  • 如果您在应用程序冻结时暂停应用程序,主线程的回溯中是什么?
  • 其实你什么都没做我的意思是你在主线程中,并且在主线程中调度块
  • 如果图像只是文件,我不会认为您需要异步发送任何东西;只需加载图像。如果您的图像文件非常大,请考虑在单元格中加载更快的缩略图。

标签: ios swift uicollectionview


【解决方案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。在下载发生并且您在“可重用单元”中使用它之前,该线程不会被释放,很明显您的应用程序会卡住!

解决方案

有许多最受欢迎的库,例如 AlamofireImageSDWebImageKingfisher。我从中获取“SDWebImage”,您可以通过以下代码以async 方式调用加载图像:

imageView.sd_setImage(with: url , placeholderImage: nil)

另外,请参阅此 SO 问题 (how to implement lazy loading of images in table view using swift) 了解更多详情。

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    相关资源
    最近更新 更多