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

如何处理Alamofire异步问题?TableView跳转数据异常求助

解决Alamofire异步请求导致TableViewCell跳转时数据未就绪的问题

你遇到的核心问题是网络请求的异步特性:点击cell后你立刻调用了performSegue,但此时getPastData里的Alamofire请求还在后台执行,数据还没返回,所以目标页面拿到的自然是空数组;再次点击时显示的错误数据,其实是上一次请求完成后遗留的旧数据。

下面是具体的修复方案和优化建议:


方案:等待异步请求完成后再执行跳转

把performSegue移到Alamofire的回调闭包里,确保数据完全获取并赋值后,再跳转到目标页面。同时优化代码的安全性,避免强制解包导致崩溃:

class CurrencyExchangeViewController: UIViewController,UITableViewDelegate, UITableViewDataSource { 
    let exchange = currencyExchangeModel() 
    var past30DaysDateValueToPass = [String]() 
    var past30DaysPriceValueToPass = [Double]() 
    var valueToPass = "" 

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
        let currentCell = tableView.cellForRow(at: indexPath) as? CurrencyExchangeTableViewCell 
        valueToPass = Array(self.exchange.currencyToGetExchangesDictionary.keys)[indexPath.row] 
        
        // 发起请求,等数据就绪后再跳转
        self.getPastData(currency: valueToPass) { [weak self] in
            guard let self = self else { return }
            self.performSegue(withIdentifier: "currencyHistorySegue", sender: self)
        }
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
        if (segue.identifier == "currencyHistorySegue") { 
            let viewController = segue.destination as? CurrencyHistoricalDataViewController 
            viewController?.historicalCurrency = valueToPass 
            viewController?.past30DaysPrice = self.exchange.currencyPast30DaysPriceArray 
            viewController?.past30DaysDate = self.exchange.currencyPast30DaysDatesArray 
        } 
    } 

    // 修改方法,添加完成回调闭包
    func getPastData(currency: String, completion: @escaping () -> Void){ 
        Alamofire.request("https://api.coindesk.com/v1/bpi/historical/close.json?currency=\(currency)").responseJSON{ (responseData) in 
            // 先清空旧数据,避免复用错误
            self.exchange.currencyPast30DaysDatesArray.removeAll()
            self.exchange.currencyPast30DaysPriceArray.removeAll()
            
            if let responseJSON = responseData.result.value as? [String: Any],
               let bpiDict = responseJSON["bpi"] as? [String: Double] {
                self.exchange.currencyPast30DaysDatesArray = Array(bpiDict.keys)
                self.exchange.currencyPast30DaysPriceArray = Array(bpiDict.values)
            } else {
                print("请求失败或数据格式异常")
            }
            // 无论成功失败,都触发回调
            completion()
        } 
    } 
}

额外优化建议

  • 添加加载状态:点击cell后显示ActivityIndicator,避免用户误以为界面无响应,请求完成后再隐藏。
  • 避免循环引用:在闭包中使用[weak self],防止内存泄漏。
  • 安全解包:替换原代码中的强制解包responseJSON!,用可选绑定的方式处理数据,避免崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:46:14