来自调试器的消息:由于内存问题而终止,在带有gif图像的UITableView / UICollectionView中滚动时,翠鸟库

时间:2019-03-01 07:56:12

标签: ios swift uitableview uicollectionview kingfisher

代码段

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
            }
}

在上面的代码中,每当以下代码加载某些图像(GIF,JPEG,PNG)时,我都会使用Kingfisher库从远程服务器加载图像,这些图像可能较大(大约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

请帮助我解决以上问题。

3 个答案:

答案 0 :(得分:1)

我在加载图像时遇到很多问题。我不确定您的情况,但可以给您一些有用的提示。

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

答案 1 :(得分: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
        }

答案 2 :(得分: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]

在上面的 options 属性代码中,我使用了自己的缓存(ImageCache(name:“ your_cache_name”)),并要求翠鸟在后台解码图像