在 CollectionView 中使用 SDWebImage 的疯狂内存问题(在 tableviewCell 内)
Posted
技术标签:
【中文标题】在 CollectionView 中使用 SDWebImage 的疯狂内存问题(在 tableviewCell 内)【英文标题】:Crazy Memory Issues using SDWebImage in a CollectionView (inside a tableviewCell) 【发布时间】:2019-02-21 20:58:53 【问题描述】:当我开始滚动带有由 SDWebImage 填充的图像视图的集合视图时,我无法弄清楚为什么我的应用程序的内存会迅速增加。如果它们还没有下载,那么一段时间就可以了。但是一旦下载了每张图片,如果我什至触摸滚动条,应用程序 ui 就会变得无响应并且内存猛增(超过 1GB),以至于不仅应用程序崩溃,整个操作系统也崩溃并重新启动。
我有一个包含几个单元格的 tableview,其中一个有一个可以滚动的 collectionview。我有一个数据对象,用于填充 collectionViewCell 中的所有标签和图像。 cellForItem 非常复杂(很多 if 语句和 switch 语句),所以我尝试将一些代码从那里移出,并将其移至我在 collectionViewCell 中设置的属性的 didSet 方法以保存数据对象。然后我只是将数据对象设置为 itemForRow 中的属性(在后台线程中),它触发了单个 collectionViewCell 的 didSet 方法来填充标签并使用 sd_set_image 方法设置图像。下面是tableViewCell上的相关代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
print(indexPath.row)
if itemStyle == .Grid
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.resourceCellIdentifier, for: indexPath) as! ResourceCollectionViewCell
cell.delegate = self
cell.tag = indexPath.row
if self.filter == Filter.Collections || self.resourceArray?[indexPath.row].actionContent == nil
let resource: ActionContentTemplate?
if self.filter == Filter.Collections
resource = self.collectionResourceArray?[indexPath.row].actionContentTemplate
else
resource = self.resourceArray?[indexPath.row].actionContentTemplate
DispatchQueue.global(qos: .userInitiated).async
cell.dataObject = resource
return cell
else .....
这是 CollectionViewCell 本身的 didSet 方法:
var dataObject: ActionContentTemplate?
didSet
var cellRow: Int = 0
if self.actionContentTemplate != nil
....
DispatchQueue.main.async
cellRow = self.tag
.....
switch self.actionContentTemplate?.contentTypeID?.uintValue
case ContentTypeVideo.rawValue,
ContentTypeVideoRecording.rawValue,
ContentTypeScreenRecording.rawValue:
.......
case ContentTypeAttachment.rawValue:
let fileType = (self.actionContentTemplate?.contentFileName as NSString?)?.pathExtension.lowercased()
var placeholderImage: UIImage
if fileType == "pdf"
placeholderImage = UIImage(named: "pdf")!
else if fileType == "doc"
placeholderImage = UIImage(named: "doc")!
else if fileType == "docx"
placeholderImage = UIImage(named: "doc")!
else if fileType == "xls"
placeholderImage = UIImage(named: "xls")!
else if fileType == "xlsx"
placeholderImage = UIImage(named: "xls")!
else if fileType == "ppt"
placeholderImage = UIImage(named: "ppt")!
else if fileType == "pptx"
placeholderImage = UIImage(named: "ppt")!
else
placeholderImage = UIImage(named: "plain")!
if let urlString = self.actionContentTemplate?.thumbnailURL
let imageURL = URL(string: urlString)
SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) (image, data, err, cacheType, finished, url) in
DispatchQueue.main.async
if cellRow == self.tag
self.activityIndicator?.stopAnimating()
self.imageView.image = image
UIAnimation.fadeTransitionImageView(self.imageView)
else
DispatchQueue.main.async
self.activityIndicator?.stopAnimating()
self.imageView.image = placeholderImage
break
.....
我实际上切换到 loadImage 方法,因为 sd_setimage 方法也不起作用。
SDWebImageManager.shared().loadImage(with: imageURL, options: [.continueInBackground, .scaleDownLargeImages], progress: nil) (image, data, err, cacheType, finished, url) in
DispatchQueue.main.async
if cellRow == self.tag
//IF I COMMENT OUT THESE TWO LINES BELOW THE ISSUES STOP (I think it is only the self.imageView.image = image line that is causing issues)
// self.activityIndicator?.stopAnimating()
// self.imageView.image = image
UIAnimation.fadeTransitionImageView(self.imageView)
谁能向我解释为什么会发生这种情况以及我可以做些什么来解决它?
编辑 - 忘记在应用委托中添加这些设置来提问:
//Settings for image caching
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
[[[SDImageCache sharedImageCache] config] setShouldDecompressImages:NO];
[[[SDImageCache sharedImageCache] config] setShouldCacheImagesInMemory:NO];
[[[SDImageCache sharedImageCache] config] setMaxCacheSize:1024 * 1024 * 100];
[[[SDImageCache sharedImageCache] config] setMaxCacheAge:3600 * 24 * 7];
[[SDImageCache sharedImageCache] setMaxMemoryCost:1024 * 1024 * 15];
【问题讨论】:
【参考方案1】:原来缩略图相当大,使用此链接 (ios Swift: How to properly scale down an image?) 将图像调整为 imageView 大小完全解决了内存问题。然而,图像下载后滚动有点不稳定......我认为将尽可能多的计算代码移动到后台线程并移出 cellForItem 会有所帮助,但我显然错过了一些东西。如果有人能指出我正确的方向,那将不胜感激,因为作为开发人员,我一直在努力学习更多知识。
【讨论】:
以上是关于在 CollectionView 中使用 SDWebImage 的疯狂内存问题(在 tableviewCell 内)的主要内容,如果未能解决你的问题,请参考以下文章
在带有 xib 文件的 UIView 中使用 CollectionView
如何在所有设备中使用 swift4 在 CollectionView 中显示两列
CollectionView 中的 CollectionView:使用 didSelectItemAt 执行Segue
在 Swift 3 中使用 CGSize 的 collectionView 的 100% 宽度