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

Swift 3图片缓存问题:滚动时图片重复下载如何解决?

解决图片重复下载的缓存逻辑修复方案

兄弟,你的问题核心在于缓存检查的顺序完全搞反了!你现在是先发起网络请求,等下载完才去看缓存——这等于每次调用updateUI都会先触发下载,缓存根本没起到拦截作用,难怪滚动时一直重复下载。

我帮你梳理下问题点,再给出修复后的代码:

原代码的核心问题

  1. 缓存检查时机错误:网络请求发起后才检查缓存,等于白做缓存,每次都会先请求网络
  2. 强制解包风险:imageToCache!如果图片数据转UIImage失败,会直接崩溃
  3. 缓存Key不严谨:用thumbnailURL as AnyObject作为Key,Swift的String是值类型,桥接成AnyObject不够稳定
  4. 未处理循环引用:网络回调里直接用self,可能导致内存泄漏

修复后的完整代码

var episode: Product! { didSet { self.updateUI() } }
// 优化NSCache类型,指定Key为NSString,Value为UIImage,更严谨
let imageCache = NSCache<NSString, UIImage>()

func updateUI() {
    // 先更新文本类UI,避免复用旧数据
    menuItemNameLabel?.text = episode.title
    ingredientsItemLabel?.text = episode.summary
    priceItemLabel?.text = episode.price
    // 设置默认占位图
    menuItemImageView?.image = UIImage(named: "Koulourades")
    
    guard let thumbnailURLStr = episode.thumbnailURL else {
        return // 如果没有图片URL,直接返回
    }
    // 把URL字符串转为NSString,作为缓存的Key(NSCache更适合用引用类型当Key)
    let cacheKey = thumbnailURLStr as NSString
    
    // 第一步:优先检查缓存!
    if let cachedImage = imageCache.object(forKey: cacheKey) {
        menuItemImageView?.image = cachedImage
        return // 有缓存直接显示,不用发起网络请求
    }
    
    // 没有缓存才发起网络请求
    let networkService = NetworkService(url: thumbnailURLStr)
    // 用[weak self]避免循环引用
    networkService.downloadImage { [weak self] imageData in
        guard let self = self, let validData = imageData else {
            return // 处理self已释放或数据为空的情况
        }
        // 回到主线程更新UI
        DispatchQueue.main.async {
            guard let imageToCache = UIImage(data: validData) else {
                // 图片转失败时,保持占位图,也可以加错误提示
                return
            }
            // 存入缓存
            self.imageCache.setObject(imageToCache, forKey: cacheKey)
            // 显示图片
            self.menuItemImageView?.image = imageToCache
        }
    }
}

关键修改点解释

  • 缓存检查前置:现在进入updateUI后第一时间检查缓存,有缓存直接显示,彻底避免重复请求
  • 弱引用self:防止网络回调时ViewController被强引用导致内存泄漏
  • 安全的可选值处理:去掉所有强制解包,转图片失败时不会崩溃,容错性更强
  • 严谨的缓存Key:用NSString作为NSCache的Key,比AnyObject更稳定,避免桥接问题

额外优化建议(可选)

如果你的图片是在TableView/CollectionView的Cell里使用,建议再加个请求取消逻辑:当Cell被复用时,取消之前未完成的图片请求,避免无用的网络请求浪费资源。当然,如果不想自己写这么多逻辑,也可以直接用成熟的第三方库(比如Kingfisher、SDWebImage),它们已经帮你封装好了缓存、请求取消、错误处理等所有逻辑。

内容的提问来源于stack exchange,提问作者Panagiotis Goutzianas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:44:12