Swift调用GIPHY API加载动图到UITableView报NSUnknownKeyException
崩溃根因
- 核心崩溃触发点:你已经通过
Codable完成了JSON到模型的转换,却错误地使用Objective-C时代的KVC(value(forKey:))方式取值,且取值的目标对象完全错误。 - 你在
fetchGiphyData中写的let gifImages = [gifs],是把整个接口返回的根模型GiphyResponseData(这个结构体只有data一个属性,根本没有url字段)包成了数组,遍历的时候对这个根对象取url字段,直接触发KVC不兼容的崩溃。另外Swift原生结构体本身就不支持这种KVC取值方式,完全没必要这么写。 - 日志里的
boringssl_metrics_log_metric_block_invoke是iOS系统底层的调试日志,和本次崩溃无关,直接忽略即可。 - 额外隐患:你当前的cell图片加载逻辑没有处理UITableView复用,滑动的时候会出现图片错位、重复加载的问题。
修复方案
1. 修正数据解析逻辑
你自己定义的模型层级是清晰的:GiphyResponseData.data是图片信息数组,每个元素下的images.original就是存了动图url的GiphyData对象,直接用点语法访问属性即可,完全不需要KVC。
替换原有fetchGiphyData方法代码:
func fetchGiphyData() { let request = AF.request("https://api.giphy.com/v1/gifs/trending?api_key=zONZGFIbbvYDBjLEBlgKxLjbsClfmptw&limit=25&rating=pg-13") request.responseDecodable(of: GiphyResponseData.self) { (response) in // 先处理请求错误,方便排查问题 if let error = response.error { print("GIPHY接口请求失败: \(error.localizedDescription)") return } guard let responseModel = response.value else { return } // 直接映射提取所有动图的original地址 self.giphyImage = responseModel.data.map { $0.images.original } // UI刷新必须放在主线程 DispatchQueue.main.async { self.giphyTableView.reloadData() } } }
2. 修复UITableView复用导致的图片错位问题
首先在GiphyTableViewCell类中添加请求持有属性和复用重置逻辑:
class GiphyTableViewCell: UITableViewCell { @IBOutlet weak var giphyImage: UIImageView! // 持有图片加载请求,方便复用的时候取消 var imageLoadRequest: DataRequest? override func prepareForReuse() { super.prepareForReuse() // 复用时取消上一个未完成的请求,清空图片 imageLoadRequest?.cancel() giphyImage.image = nil } }
再替换原有cellForRowAt方法代码:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! GiphyTableViewCell let gifModel = giphyImage[indexPath.row] // 发起图片请求并持有 cell.imageLoadRequest = AF.request(gifModel.url).responseImage { response in // 校验当前cell是否还对应当前indexPath,避免复用时错图 guard let currentIndexPath = tableView.indexPath(for: cell), currentIndexPath == indexPath, case .success(let image) = response.result else { return } cell.giphyImage.image = image } return cell }
改完之后崩溃问题会直接解决,滑动列表也不会出现图片错位的情况。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

