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

Swift解析NHL standings JSON:获取完整球队信息数组

解决NHL API完整球队数据获取问题

看起来你已经成功解析了API返回的数据,但卡在了从嵌套的Records结构中提取完整球队记录这一步。问题出在你目前只把球队名字存到了扁平数组里,但核心的TeamRecord(包含战绩、积分、排名等)还是嵌套在standingData的分区结构中,导致你在tableView里无法正确索引到对应球队的完整数据。

核心问题分析

你的standingData是[Records]类型,每个Records对应一个分区,里面包含多个TeamRecord。但你在cellForRowAt里尝试用indexPath.row直接访问standingData[indexPath.row].teamRecords[indexPath.row],这明显是错误的:

  • standingData的元素数量是分区数(远小于球队总数),直接用indexPath.row访问会导致数组越界
  • 每个分区的球队数量不同,无法用同一个索引同时定位分区和分区内的球队

解决方案:扁平化存储所有TeamRecord

我们不需要单独存球队名字数组,而是直接把所有分区的TeamRecord提取到一个扁平数组里,这样每个tableView行就能直接对应一个完整的球队记录。

修改后的代码

1. 更新ViewController的属性

把原来的standingData和standings替换成一个扁平的TeamRecord数组:

import UIKit
class StandingsTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var standingsURL: URL = URL(string: "https://statsapi.web.nhl.com/api/v1/standings")!
    @IBOutlet weak var tableView: UITableView!
    // 替换原来的两个数组,直接存储所有球队的完整记录
    var allTeamRecords: [TeamRecord] = []
    let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        loadStandings()
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
    
    // ... 其他原有方法不变 ...

2. 修改数据解析逻辑

在dataLoaded方法里,遍历所有分区的teamRecords,把它们全部添加到扁平数组中:

func dataLoaded(data:Data?,response:URLResponse?,error:Error?){
    if let standingsDetailData = data{
        let decoder = JSONDecoder()
        do {
            let jsondata = try decoder.decode(Initial.self, from: standingsDetailData)
            // 清空数组(避免重复加载)
            allTeamRecords.removeAll()
            // 遍历所有分区,把每个分区的球队记录添加到扁平数组
            for record in jsondata.records ?? [] {
                allTeamRecords.append(contentsOf: record.teamRecords)
            }
            // 可以打印第一个球队的完整数据验证
            print(allTeamRecords.first ?? "No data")
            DispatchQueue.main.async{
                self.tableView.reloadData()
                self.activityIndicator.removeFromSuperview()
            }
        }catch let error{
            print(error)
        }
    }else{
        print(error!)
    }
}

3. 更新TableView数据源方法

现在可以直接用扁平数组来提供数据,避免索引错误:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return allTeamRecords.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "standingsCell", for: indexPath) as! standingsCell
    let teamRecord = allTeamRecords[indexPath.row]
    // 赋值球队名称
    let teamName = teamRecord.team.name
    cell.teamImage.image = UIImage(named: teamName)
    // 赋值战绩、积分等数据
    cell.gamesPlayed.text = "\(teamRecord.gamesPlayed)"
    cell.wins.text = "\(teamRecord.leagueRecord.wins)"
    cell.loses.text = "\(teamRecord.leagueRecord.losses)"
    cell.overTime.text = teamRecord.leagueRecord.ot.map { "\($0)" } ?? "0"
    cell.points.text = "\(teamRecord.points)"
    return cell
}

额外提示

  • 注意leagueRecord.ot是可选值,所以用map来安全解包,避免崩溃
  • 如果你的standingsCell还没有对应IBOutlet,记得在Storyboard里把label和代码关联起来
  • 可以考虑给TeamRecord添加自定义的description方法,方便调试时查看完整数据

内容的提问来源于stack exchange,提问作者Brent Le Comte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:46:08