UICollection 在使用 Swift 3 显示图像时非常慢

Posted

技术标签:

【中文标题】UICollection 在使用 Swift 3 显示图像时非常慢【英文标题】:UICollection is very slow in showing Image with Swift 3 【发布时间】:2017-03-29 08:31:10 【问题描述】:

我正在使用 UICollectionView 在我的应用中显示图像。 问题是显示图像的速度非常慢。 50 秒后,将出现集合视图中的图像。 :( 当我在谷歌找到解决方案时,他们大多编写以下代码。 但这对我来说行不通

  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale

extension SeeAllCollectionView 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    debugPrint("seeAllLIStCell Count \(assetsTable.count)")
    return assetsTable.count


override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 


    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "seeAllListCell", for: indexPath) as! SeeAllPhotoCell

    let list = assetsTable[(indexPath as NSIndexPath).row]


    var imageName: String? = (list.poster_image_url)
    var image: UIImage? = (images_cache[imageName!])
    if image != nil 
        debugPrint("Yes Image")

        cell.imageView.image = image

     else
        debugPrint("NO Image")
        cell.imageView.image = nil

        DispatchQueue.main.async()
            let url = NSURL(string: list.poster_image_url)
            let data = NSData(contentsOf:url! as URL)
            var image = UIImage(data: data as! Data)
            DispatchQueue.main.async(execute: () -> Void in
                cell.movieTitle.text = list.name
                cell.imageView?.image = image
            )
            self.images_cache[imageName!] = image
        

    




    return cell





// MARK: - UICollectionViewDelegate

extension SeeAllCollectionView 

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 

            debugPrint("Selected")


    let list = assetsTable[(indexPath as NSIndexPath).row]
    debugPrint(list.poster_image_url)
    debugPrint(list.name)

    prefs.set(list.poster_image_url, forKey: "poster_image_url")
    prefs.set(list.name, forKey: "name")
    prefs.set(list.assets_id, forKey: "VIDEO_ID")
    prefs.set(false, forKey: "FLAG")
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "DetailsChannel") as UIViewController
            self.present(vc, animated: true, completion: nil)


这是我运行项目时的屏幕截图。我运行时得到了这么多行代码。

请任何人帮助我该怎么办?

【问题讨论】:

显示您的代码,因为您似乎做错了什么。关于从后台线程修改自动布局的错误是明确的,并且已经在 SO 上得到了回答。如果您不显示代码,我们无法猜测在哪里以及为什么。以及为什么要写cell.layer.rasterizationScale = UIScreen.main.scale @Larme,您好,我更新了我的帖子。请复习一下,为什么我写 cell.layer 代码是因为我发现有人写这个代码来解决问题。 【参考方案1】:

当我从 API 调用获取数据并重新加载 UITableView(根据我的要求)时,我得到了相同的 console error。我的问题通过使用解决了

DispatchQueue.global(qos: .background).async  // load data in back ground mode so that main thread can be safed.
let url = NSURL(string: list.poster_image_url)
            let data = NSData(contentsOf:url! as URL)
            var image = UIImage(data: data as! Data)
    DispatchQueue.main.async(execute: 
                                cell.movieTitle.text = list.name
                cell.imageView?.image = image
                            ) 
self.images_cache[imageName!] = image       
        

我之前在控制台上遇到的错误的屏幕截图

【讨论】:

你好兄弟@agent_stack,我也使用这个代码。请检查我更新的问题。我上传我的代码。谢谢。 :) 我试过兄弟@agent_stack。但还是不行。我的过程是我从服务器中提取数据。到达此收藏页面后,拉取过程就完成了。我也查了一下调试区。为了将这些拉取的数据显示到 UIview,它花费了很多时间,并且在调试区域中得到了上述警告。 @MayPhyu bro,如果您的图像提取过程在您的 UICollectionView 中显示之前完成,为什么您再次从 URL 获取图像?? 兄弟 @agent_stack ,我们在服务器中存储了一千张图像,我们一次提取 10 张图像,然后在集合视图中显示它们。之后,我们提取接下来的 10 张图像。 我从 assets 文件夹中获取图像时出现了延迟,例如“img1.jpg”,....,你能给我一些建议吗?【参考方案2】:

你可以尝试SDWebimage所有异步线程操作维护良好。

这可以提供以下优点

异步下载

如果应用发生内存警告,则自动清除图像缓存

图片网址缓存

图像缓存

避免重复下载

您可以直接在单元格中使用单个方法,如下所示

[cell.storeImg sd_setImageWithURL:[NSURL URLWithString:strURL] placeholderImage:kDefaultImageForDisplay];

在您的代码中,以下行应该会产生问题,因为该操作可能发生在主线程上 让 data = NSData(contentsOf:url! as URL)

【讨论】:

【参考方案3】:

这一行:

DispatchQueue.main.async()

在下载图像时可能会导致错误,它会阻塞主线程并在主(UI)队列上执行网络请求,更不用说这些请求随后会串行执行(因此很慢)。尝试将sn-p更改为:

DispatchQueue.global.async(qos: DispatchQoS.QoSClass.background)
        let url = NSURL(string: list.poster_image_url)
        let data = NSData(contentsOf:url! as URL)
        var image = UIImage(data: data as! Data)
        DispatchQueue.main.async(execute: () -> Void in

其中global 代表此类网络操作的全局队列默认值。

编辑:除了使用主队列进行网络调用之外,实际上可能存在为当前在屏幕上不可见的行加载的图像过多的问题。如果它们很多并且连接不太好,您最终将获得屏幕单元的应用程序待下载。考虑仅对屏幕单元格延迟加载图像 - 并取消不可见行的下载。在 Swift 中有一个相当不错的 tutorial (但是对于表格视图,但您可以轻松地将其扩展为收藏)关于如何实现这一点。

【讨论】:

兄弟@WladekSurala,我使用你的代码。但我得到的错误是“对成员'global(priority:)'的模糊引用”。 @MayPhyu 尝试将此调用替换为 - DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async \\download code here 兄弟@WladekSurala,还是一样。仍然很慢并在命令行中显示以上行。 会有很多行。我从服务器中提取数据。到达此收藏页面后,拉取过程就完成了。我也查了一下调试区。为了将这些拉取的数据显示到 UIview,它花费了很多时间,并且在调试区域中得到了上述警告。

以上是关于UICollection 在使用 Swift 3 显示图像时非常慢的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS swift 中的 ARSCNView 中显示 uicollection 视图

Swift - 如果项目滚动一点,UICollection 快速恢复

Swift 3 - iOS 11.2上的UICollectionview问题

在单独的 UICollection 类中使用未解析的标识符“UICollection”

集合视图不会重新加载(Swift)

如何在 UICollection 补充视图中使用 UIButton?