You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

横向CollectionView滚动时卡顿崩溃,报内存不足终止错误

解决CollectionView滚动卡顿+内存崩溃问题(Kingfisher场景)

兄弟,我太懂这种滚动到一半突然崩掉的糟心感了!结合你用Kingfisher加载图片的场景,大概率是CollectionView的图片加载/复用环节出了内存泄漏或者资源占用过高的问题,给你几个针对性的解决办法:


1. 先把Cell复用和清理做对,这是最常见的坑

首先检查你在collectionView(_:cellForItemAt:)里的cell复用逻辑——绝对不要每次都创建新Cell,必须用复用池的cell:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionCell", for: indexPath) as! FilterCollectionCell
    // 这里设置图片等内容
    return cell
}

然后一定要在FilterCollectionCell里重写prepareForReuse()方法,取消正在进行的图片下载任务并清空旧图——不然复用的时候,之前的下载任务还在后台跑,内存会越堆越多:

class FilterCollectionCell: UICollectionViewCell {
    @IBOutlet weak var imageView: UIImageView!
    
    override func prepareForReuse() {
        super.prepareForReuse()
        // 取消当前图片下载任务,释放资源
        imageView.kf.cancelDownloadTask()
        // 清空旧图片,避免复用的时候显示错误内容+占用内存
        imageView.image = nil
    }
}

2. 给Kingfisher的图片加载「瘦个身」

默认的Kingfisher加载逻辑可能会直接下载原图,而CollectionViewCell的图片尺寸通常很小,这会导致内存里存了大量超大尺寸的图片,直接撑爆内存。

给图片做「降采样」(强制缩小到Cell需要的尺寸)

比如你的Cell里imageView是100x100的,就用DownsamplingImageProcessor让Kingfisher直接加载缩小后的图:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionCell", for: indexPath) as! FilterCollectionCell
    let imageUrl = yourDataSource[indexPath.item].imageUrl
    // 根据imageView的尺寸创建处理器
    let downsampleProcessor = DownsamplingImageProcessor(size: cell.imageView.bounds.size)
    cell.imageView.kf.setImage(
        with: URL(string: imageUrl),
        placeholder: UIImage(named: "default_placeholder"),
        options: [
            .processor(downsampleProcessor),
            .scaleFactor(UIScreen.main.scale), // 适配屏幕分辨率
            .cacheOriginalImage // 可选:如果需要缓存原图的话可以保留,否则可以去掉
        ]
    )
    return cell
}

限制Kingfisher的内存缓存大小

全局配置一下内存缓存的上限,避免它无限制缓存图片:

// 可以在App启动的时候(比如AppDelegate/SceneDelegate的didFinishLaunchingWithOptions里)配置
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 内存缓存上限设为100MB(根据你的APP需求调整)
    ImageCache.default.memoryStorage.config.totalCostLimit = 100 * 1024 * 1024
    // 最多缓存200张图片(可选)
    ImageCache.default.memoryStorage.config.countLimit = 200
    return true
}

3. 优化CollectionView的渲染性能

如果Cell里有圆角、阴影这类耗时的渲染操作,会导致滚动卡顿,同时也会间接增加内存占用:

// 在Cell的awakeFromNib或者配置的时候开启光栅化
class FilterCollectionCell: UICollectionViewCell {
    override func awakeFromNib() {
        super.awakeFromNib()
        // 开启光栅化,把Cell的渲染结果缓存起来,滚动时不用重复渲染
        layer.shouldRasterize = true
        layer.rasterizationScale = UIScreen.main.scale // 必须和屏幕分辨率一致,不然会模糊
    }
}

另外,确保你的CollectionView的布局是提前计算好的,比如用UICollectionViewFlowLayout的话,提前设置好itemSize,不要让系统在滚动时动态计算,这也会导致卡顿和额外的内存消耗。


4. 排查内存泄漏

用Xcode的Memory Graph Debugger(调试栏里的那个小方块图标)看看是不是有循环引用:

  • 比如在Kingfisher的回调闭包里,如果引用了self,一定要用weak self避免循环引用:
    cell.imageView.kf.setImage(with: URL(string: imageUrl)) { [weak self] result in
        guard let self = self else { return }
        // 这里处理图片加载完成后的逻辑,比如更新UI
    }
    
  • 另外,检查你的数据源模型——绝对不要在模型里存储UIImage对象,只存图片URL即可,让Kingfisher负责加载和缓存,不然数据源会占用大量内存。

按照上面的步骤一步步排查,大概率能解决你的滚动卡顿和内存崩溃问题!

内容的提问来源于stack exchange,提问作者Yasheed Mohammed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:15:40