来自调试器的消息:由于内存问题而终止使用gif图像在UITableView / UICollectionView中滚动Kingfisher Library

问题描述 投票:1回答:3

代码片段

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: BroadCastFeedTableViewCell = broadCastTableView.dequeueReusableCell(withIdentifier: "broadCastFeedCell") as BroadCastFeedTableViewCell

    cell.singlePicImageView.kf.setImage(with: URL(string: (self.broadCastArray[indexPath.row].images_url?[0])!), placeholder: nil, options: nil, progressBlock: nil) 
            { (theImage, error, cache, url) in
                if theImage != nil{
                    let imageHeight = self.getAspectRatioOfDownloadedImages(resolution: self.broadCastArray[indexPath.row].image_resolution![0])
                    cell.collectionContentViewHeightConstraint.constant = imageHeight

                    cell.layoutSubviews()
                    cell.layoutIfNeeded()

                }else {
                    let placeHolderCenterCordi = UIView().getViewRelationWithSuperSuperView(viewControllerView: cell.collectionContentView, 
                                                                    subView: cell.singlePicImageView, subObjFrame: cell.singlePicImageView.frame)

                    cell.singlePicImageView.addPlaceHolderImageView(cordinates: placeHolderCenterCordi.center)
                }
               self.broadCastTableView.rowHeight = UITableViewAutomaticDimension
            }
}

在上面的代码中,我使用Kingfisher库从远程服务器加载图像,每当下面的代码加载某些图像(GIF,JPEG,PNG)时,可能有大尺寸(约2-5 MB)应用程序因内存问题而终止。在iPhone 5s中,它会在应用程序启动后立即终止,而在其他iPhone型号(7,6s)中,它会在滚动一段时间后终止。我也检查了分配和泄漏,但我不明白/发现了很多关于这个问题。

我还附上了分析图

Following Image show their is no such memory leaks, but due to some issue app is terminating

请帮我解决上述问题。

ios swift uitableview uicollectionview kingfisher
3个回答
1
投票

我在内存加载图像方面遇到了很多问题。我不能确定你的情况,但我可以给你一些有用的提示。

  1. 查看UITableViewDataSourcePrefetching。这是一种在图像呈现之前下载图像的方法。
  2. 考虑在某个地方创建一个Helper功能,启动下载并允许取消下载。例如,当你快速向下滚动一个tableview时,每个单元格都将开始下载图像,即使它没有显示。如果单元格消失,您可以取消下载。
  3. 单元格应该基本上是代码中的UI元素。我的想法是,尝试从单元格本身中取出网络请求,并确保单元格只包含要渲染的元素(图像,标签,视图),单元格具有func configure(withModel:Model)函数,并且在cellForRow上,您只需将数据传递给它进行渲染。单元格经常被重复使用和更新,你不应该在它上面执行大量的工作。请记住,当一个单元格被加载时,它将调用这些函数,然后它可以退出屏幕并再次返回,它将重新执行所有这些操作。
  4. 您是否有单元类执行正确的布局更新和刷新,并尝试不在cellForRow中执行此操作。您所能做的就是确保imageview获取图像,但不依赖于执行单元格更改,并且此图像下载是异步的,并且下载结束时该单元格可能甚至不存在。
  5. 缓存。你能缓存这些图像还是不断变化?确保您了解KF如何缓存您的图像,并且正在进行您需要的缓存。如果没有,请适应。
  6. [挑剔]你打电话给cell.layoutSubviews()然后cell.layoutIfNeeded()。第一个是强制调用layoutSubviews,第二个是在调用layoutSubView之前检查是否有需要布局的东西。如果要标记要布局的视图,可以执行setNeedsLayout()。这将使视图布局在下一个周期更新。

0
投票

我认为在你的代码中你使用“Self”作为一个强烈的禁止因此它创建了一个强大的参考周期,因为这会造成内存泄漏。所以在这一点上你可以尝试[弱自我]而不是运行你的代码

cell.singlePicImageView.kf.setImage(with: URL(string: (self.broadCastArray[indexPath.row].images_url?[0])!), placeholder: nil, options: nil, progressBlock: nil) 
        { [weak self] (theImage, error, cache, url) in
            if theImage != nil{
                let imageHeight = self?.getAspectRatioOfDownloadedImages(resolution: self?.broadCastArray[indexPath.row].image_resolution![0])
                cell.collectionContentViewHeightConstraint.constant = imageHeight

                cell.layoutSubviews()
                cell.layoutIfNeeded()

            }else {
                let placeHolderCenterCordi = UIView().getViewRelationWithSuperSuperView(viewControllerView: cell.collectionContentView, 
                                                                subView: cell.singlePicImageView, subObjFrame: cell.singlePicImageView.frame)

                cell.singlePicImageView.addPlaceHolderImageView(cordinates: placeHolderCenterCordi.center)
            }
           self?.broadCastTableView.rowHeight = UITableViewAutomaticDimension
        }

0
投票

回答我自己的问题

以下为我工作

我为Kingfisher库提供的UIImageView使用了AnimatedImageView类

let imageView = AnimatedImageView()
imageView.kf.setImage(with: URL(string: "your_image"), placeholder: nil, options: [.targetCache(ImageCache(name: "your_cache_name")), .backgroundDecode], progressBlock: nil) { (image, error, cache, url) in 
  // some code
}

注意重要

[.targetCache(ImageCache(name:“your_cache_name”)),. backgroundDecode]

在上面的选项代码属性中,我使用了自己的缓存(ImageCache(名称:“your_cache_name”))并要求翠鸟在背景中解码图像

© www.soinside.com 2019 - 2024. All rights reserved.