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
相关产品推荐
相关产品推荐

