【发布时间】:2023-03-05 01:00:01
【问题描述】:
我查看了这个问题的几个答案,但没有任何帮助。
vc1 是一个普通的 vc,我从 firebase 中抓取了 20 张图片,在 vc2 中,我使用 ARKit 在用户选择时显示这些图片。我在 vc2 中有一个 collectionView,它对来自 firebase 的 20 多个图像进行分页。问题是当接下来的 20 张图片正在加载并且我开始滚动时,应用程序崩溃并显示 Message from debugger: Terminated due to memory issue。当滚动这些新图像时,我查看了内存图,它会上升到 1 gig,所以这就是崩溃的原因。 ARKit 和我浮动的节点也会导致内存增加,但它们不是导致崩溃的原因,如下所述。
1- 在单元格内,我使用SDWebImage 在 imageView 中显示图像。一旦我注释掉SDWebImage 一切正常,滚动就很流畅,不会再出现崩溃,但我当然看不到图像。我切换到URLSession.shared.dataTask,同样的内存问题再次出现。
2- 图片最初是使用 iPhone 全屏相机拍摄的,并使用jpegData(compressionQuality: 0.3). 保存,单元格大小为 40x40。在SDWebImage 完成块内,我尝试了resize the image,但内存崩溃仍然存在。
3- 我使用Instruments > Leaks 来查找内存泄漏,并且出现了一些 Foundation 泄漏,但是当我关闭 vc2 时,Deinit 总是运行。在 vc2 内部没有任何长时间运行的计时器或循环,我在所有闭包中使用 [weak self]。
4- 正如我在第二点中所述,问题绝对是 imageView/image,因为一旦我将其从流程中删除,一切正常。如果我不显示任何图像,一切正常(将出现 40 个没有图像的红色图像视图)。
我能做些什么来解决这个问题?
分页拉取更多图片
for child in snapshot.children.allObjects as! [DataSnapshot] {
guard let dict = child.value as? [String:Any] else { continue }
let post = Post(dict: dict)
datasource.append(post)
let lastIndex = datasource.count - 1
let indexPath = IndexPath(item: lastIndex, section: 0)
UIView.performWithoutAnimation {
collectionView.insertItems(at: [indexPath])
}
}
cellForItem:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cellId, for: indexPath) as! PostCell
cell.resetAll()
cell.post = dataSource[indexPath.item]
return cell
}
后细胞
private lazy var imageView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.cornerRadius = 15
iv.layer.masksToBounds = true
iv.backgroundColor = .red
iv.isHidden = true
return iv
}()
private lazy var spinner: UIActivityIndicatorView = {
let actIndi = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium) // ...
}()
var post: Post? {
didSet {
guard let urlSr = post?.urlStr, let url = URL(string: urlSr) else { return }
spinner.startAnimating()
// if I comment this out everything works fine
imageView.sd_setImage(with: url, placeholderImage: placeHolderImage, options: [], completed: {
[weak self] (image, error, cache, url) in
// in here I tried resizing the image but no diff
DispatchQueue.main.async { [weak self] in
self?.showAll()
}
})
setAnchors()
}
}
func resetAll() {
spinner.stopAnimating()
imageView.image = nil
imageView.removeFromSuperView()
imageView.isHidden = true
}
func showAll() {
spinner.stopAnimating()
imageView.isHidden = false
}
func setAnchors() {
contentView.addSubview(imageView)
imageView.addSubview(cellSpinner)
// imageView is pinned to all sides
}
【问题讨论】:
-
“这些图像最初是用 iPhone 全屏相机拍摄的” 就是这样。您不可能一次加载 20 张相机图像。您说您的单元格大小为 40x40,因此您的图像大小需要为 40x40(或更小)。
-
@matt 在 SDWebImage 回调中,我使用 stackoverflow.com/a/31314494/4833705 调整了图像的大小。它没有工作
-
您认为一遍又一遍地添加微调器会导致任何这种情况吗?我不明白一遍又一遍地添加和删除视图的意义。可能是图像,但一遍又一遍地添加视图让我想知道。为什么不离开他们?
-
@agibson007 我完全注释掉了微调器,看看会发生什么,同样的问题。这是100%因为图像。由于细胞重复使用,我从不离开它们,并且错误的图像永远不会出现在错误的细胞上。我构建了大约 7 个应用程序或其他东西,这与我在所有应用程序中使用的程序相同,我以前从未遇到过问题。 ARKit 和节点在内存消耗方面有很大的不同。它肯定与图像有关,因为当我使用通用图像时,它可以正常工作。
-
“它不起作用”是什么意思?如果您因为使用 Instruments 很容易知道的图像而导致内存不足,那么它不会调整它们的大小。我对 SDWebImage 一无所知,但我知道从磁盘加载一个大图像文件的小版本,没有缓存,也没有内存中的大图像。
标签: ios swift memory-management uiimageview uicollectionviewcell