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

Swift:numberOfRowsInSection等方法无返回值,API数据无法加载到TableView

解决TableView无法展示API数据的问题

嘿,我来帮你搞定这个TableView加载数据的问题!从你描述的情况来看,核心问题应该是数据源数组没有正确填充,或者数据更新后没有触发TableView刷新,再加上可能的解析或可选值处理问题,导致numberOfRowsInSection和cellForRowAt没法返回正确内容。下面一步步给你修正方案:

1. 先修正模型类的可选值问题

你原来的Currency用了隐式解析可选类型(!),万一解析失败会导致崩溃或数据丢失,改成非可选类型更安全:

class Currency: NSObject {
    let name: String
    let price: Double
    
    init(name: String, price: Double) {
        self.name = name
        self.price = price
    }
}

2. 完善ViewController的数据源与请求逻辑

首先要确保ViewController正确实现TableView的代理/数据源,并且在请求到数据后必须刷新TableView:

import UIKit
import Alamofire
import SwiftyJSON

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    // 声明数据源数组,初始为空
    private var currencies = [Currency]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // 绑定TableView的代理和数据源
        tableView.dataSource = self
        tableView.delegate = self
        // 开始请求数据
        fetchCurrencyData()
    }

    // 请求并解析API数据
    private func fetchCurrencyData() {
        let apiUrl = "https://coincap.io/front"
        AF.request(apiUrl).responseJSON { [weak self] response in
            guard let self = self else { return }
            
            switch response.result {
            case .success(let rawData):
                let json = JSON(rawData)
                // 遍历API返回的数组数据
                for item in json.arrayValue {
                    // 安全解析字段:注意API返回的价格字段是`priceUsd`(字符串类型),需要转成Double
                    guard let currencyName = item["name"].string,
                          let priceString = item["priceUsd"].string,
                          let currencyPrice = Double(priceString) else {
                        // 解析失败就跳过当前元素,避免影响其他数据
                        continue
                    }
                    // 创建模型并添加到数据源
                    let currency = Currency(name: currencyName, price: currencyPrice)
                    self.currencies.append(currency)
                }
                // 必须在主线程刷新TableView!
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            case .failure(let error):
                print("数据请求失败:\(error.localizedDescription)")
            }
        }
    }

    // MARK: - TableView DataSource Methods
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // 直接返回数据源数组的长度,这样数据更新后行数会自动变化
        return currencies.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // 确保你在Storyboard里给Cell设置了正确的Identifier(这里用"CurrencyCell"举例)
        let cell = tableView.dequeueReusableCell(withIdentifier: "CurrencyCell", for: indexPath)
        let currentCurrency = currencies[indexPath.row]
        // 填充Cell内容
        cell.textLabel?.text = currentCurrency.name
        // 格式化价格为两位小数的字符串
        cell.detailTextLabel?.text = String(format: "$%.2f", currentCurrency.price)
        return cell
    }
}

3. 关键注意事项

  • 检查Cell Identifier:一定要在Storyboard/XIB里给TableViewCell设置和代码中一致的Identifier(比如上面的"CurrencyCell"),否则会崩溃。
  • API字段名确认:coincap的/front接口返回的价格字段是priceUsd(字符串类型),不是直接的price,这很可能是你之前解析不到数据的原因!
  • 主线程刷新UI:所有UI操作必须在主线程执行,Alamofire的回调默认在主线程,但加上DispatchQueue.main.async更稳妥。
  • 避免隐式解析可选:之前用!会导致解析失败时直接崩溃,用guard let安全解析能保证程序稳定性。

你之前改成整数能运行,应该是硬编码了numberOfRowsInSection的返回值(比如return 10),但实际数据源数组是空的,所以Cell里没有内容。现在按照上面的代码,数据源数组会被正确填充,并且数据更新后会触发TableView刷新,就能正常展示name和price了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:22:31