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

如何使用Swift在CollectionViewCell中显示JSON接口返回的图片

解决CollectionViewCell中加载网络图片的问题

你已经成功获取到API数据,现在需要将网络图片加载到cardImage这个UIImageView中,核心问题是不能直接通过URL同步赋值图片,必须异步加载并切换回主线程更新UI,以下是具体修改方案:

1. 修改cellForItemAt方法

在你的MainViewController的cellForItemAt方法中,替换图片加载的逻辑:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = mainCollectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell
    
    // 先设置占位图(可选,提升用户体验)
    cell.cardImage.image = UIImage(named: "placeholder")
    
    if let nextJoke = self.jokes?[indexPath.row] {
        let jokeImagePath = nextJoke.image
        guard let imageUrl = URL(string: "https://sgp1.vultrobjects.com/kaushal-meme-api/meme_api_prod/memes/" + jokeImagePath) else {
            // URL无效的情况,设置错误占位图
            cell.cardImage.image = UIImage(named: "error-placeholder")
            return cell
        }
        
        // 异步加载图片
        URLSession.shared.dataTask(with: imageUrl) { data, response, error in
            guard let data = data, error == nil, let image = UIImage(data: data) else {
                DispatchQueue.main.async {
                    cell.cardImage.image = UIImage(named: "error-placeholder")
                }
                return
            }
            // 回到主线程更新UI
            DispatchQueue.main.async {
                cell.cardImage.image = image
            }
        }.resume()
    }
    return cell
}

2. 优化方案:封装UIImageView扩展(推荐)

为了代码复用和更好的维护性,建议给UIImageView写一个加载网络图片的扩展:

extension UIImageView {
    func loadImage(from url: URL, placeholder: UIImage? = nil, errorImage: UIImage? = nil) {
        self.image = placeholder
        
        // 用NSCache缓存已加载的图片,避免重复请求
        let cache = NSCache<NSURL, UIImage>()
        if let cachedImage = cache.object(forKey: url as NSURL) {
            self.image = cachedImage
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self, let data = data, error == nil, let image = UIImage(data: data) else {
                DispatchQueue.main.async {
                    self.image = errorImage
                }
                return
            }
            // 缓存图片
            cache.setObject(image, forKey: url as NSURL)
            DispatchQueue.main.async {
                self.image = image
            }
        }.resume()
    }
}

然后在cellForItemAt中直接调用:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = mainCollectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell
    
    if let nextJoke = self.jokes?[indexPath.row] {
        let jokeImagePath = nextJoke.image
        guard let imageUrl = URL(string: "https://sgp1.vultrobjects.com/kaushal-meme-api/meme_api_prod/memes/" + jokeImagePath) else {
            cell.cardImage.image = UIImage(named: "error-placeholder")
            return cell
        }
        
        // 使用扩展方法加载图片
        cell.cardImage.loadImage(from: imageUrl, placeholder: UIImage(named: "placeholder"), errorImage: UIImage(named: "error-placeholder"))
    }
    return cell
}

3. 关键注意事项

  • 线程切换:网络请求必须在子线程执行,更新UI必须切回主线程,否则会导致崩溃或UI不更新
  • cell复用问题:快速滚动时可能出现图片错位,使用[weak self]可避免循环引用,进阶优化可在cell复用时取消未完成的请求
  • 占位图:添加占位图和错误图能避免空白状态,提升用户体验
  • 缓存机制:用NSCache缓存已加载图片,减少重复网络请求,提升加载速度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:10:57