【问题标题】:UICollection is very slow in showing Image with Swift 3UICollection 在使用 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 代码是因为我发现有人写这个代码来解决问题。

标签: swift3 uicollectionview uicollectionviewcell uicollectionviewlayout uicollectionviewdelegate


【解决方案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,它花费了很多时间,并且在调试区域中得到了上述警告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 2019-03-19
    • 2017-09-04
    • 2018-01-01
    相关资源
    最近更新 更多