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

Swift 3中如何将远程加载的图片添加到UITableView并显示?

解决UITableView远程图片显示问题

首先,你的核心问题有几个:下载完图片后没有关联到表格单元格、没有在主线程更新UI、数据结构不利于管理图片,还有没处理单元格复用的问题。我一步步帮你解决:


第一步:重构数据模型(替换拼接字符串的方式)

你现在把节目名称和类型拼成字符串存进TableData,没办法关联对应的图片。我们应该创建一个专门的模型来存储每个节目的所有信息:

struct Show {
    let name: String
    let genre: String
    let thumbnailURL: String
    var image: UIImage? // 用来缓存下载好的图片
}

然后把原来的TableData替换成存储模型的数组:

var shows: [Show] = []

解析JSON的时候,初始化Show对象并添加到数组(建议用Swift原生的字典数组,不要用NSArray/NSDictionary,更安全):

if let showsList = json as? [[String: Any]] {
    for showDict in showsList {
        guard let name = showDict["show"] as? String,
              let genre = showDict["genre"] as? String,
              let thumbnailURL = showDict["thumbnail"] as? String else {
            continue // 解析失败就跳过当前条目
        }
        let show = Show(name: name, genre: genre, thumbnailURL: thumbnailURL, image: nil)
        shows.append(show)
    }
    tableView.reloadData() // 解析完成后刷新表格
}

第二步:异步下载图片并关联到单元格

下载图片是异步操作,必须回到主线程更新UI,还要处理单元格复用的问题(避免滑动时图片错乱)。这里分两种方案:

方案1:手动实现(适合学习原理)

我们自定义一个单元格,重写prepareForReuse方法来取消未完成的下载任务,防止图片错乱:

class ShowTableViewCell: UITableViewCell {
    var downloadTask: URLSessionDataTask?
    
    override func prepareForReuse() {
        super.prepareForReuse()
        // 复用单元格时取消之前的下载任务
        downloadTask?.cancel()
        downloadTask = nil
        // 清空旧内容
        imageView?.image = nil
        textLabel?.text = nil
    }
}

然后在cellForRowAt方法里处理图片加载:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "ShowCell", for: indexPath) as? ShowTableViewCell else {
        return UITableViewCell()
    }
    
    let show = shows[indexPath.row]
    // 设置文本内容
    cell.textLabel?.text = "\(show.name) | \(show.genre)"
    // 设置占位图(可选,提升用户体验)
    cell.imageView?.image = UIImage(named: "placeholder")
    
    // 如果已经下载过图片,直接显示
    if let cachedImage = show.image {
        cell.imageView?.image = cachedImage
        return cell
    }
    
    // 没有缓存,开始下载图片
    guard let imageURL = URL(string: show.thumbnailURL) else {
        return cell
    }
    
    let task = URLSession.shared.dataTask(with: imageURL) { [weak self, weak cell] data, response, error in
        // 异步任务完成后,必须回到主线程更新UI!
        DispatchQueue.main.async {
            guard let self = self, let cell = cell else { return }
            
            if let error = error {
                print("图片下载失败:\(error.localizedDescription)")
                return
            }
            
            guard let imageData = data, let downloadedImage = UIImage(data: imageData) else {
                print("无法解析图片数据")
                return
            }
            
            // 缓存图片到模型里
            self.shows[indexPath.row].image = downloadedImage
            // 给当前单元格设置图片
            cell.imageView?.image = downloadedImage
        }
    }
    
    // 把任务赋值给单元格,方便复用的时候取消
    cell.downloadTask = task
    task.resume()
    
    return cell
}

方案2:用第三方库(推荐,适合新手)

手动实现需要处理很多细节(缓存、复用、错误处理),新手可以直接用成熟的图片加载库,比如Kingfisher:

  1. 先通过CocoaPods或Swift Package Manager安装Kingfisher
  2. 在代码中导入库,然后在cellForRowAt里一行代码搞定:
import Kingfisher

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ShowCell", for: indexPath)
    let show = shows[indexPath.row]
    
    cell.textLabel?.text = "\(show.name) | \(show.genre)"
    // Kingfisher自动处理下载、缓存、占位图和复用问题
    if let imageURL = URL(string: show.thumbnailURL) {
        cell.imageView?.kf.setImage(with: imageURL, placeholder: UIImage(named: "placeholder"))
    }
    
    return cell
}

你原来代码的核心问题总结

  1. 没有关联图片到单元格:你下载完图片只创建了UIImage,但没把它设置到cell的imageView里
  2. 没有在主线程更新UI:异步任务的回调在后台线程,UI操作必须在主线程执行,否则不会生效
  3. 数据结构不合理:用拼接字符串无法对应到每个节目的图片,必须用模型管理
  4. 没处理单元格复用:滑动表格时旧的下载任务可能还在运行,导致图片显示错乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:49:24