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

Swift解析API JSON返回空数组问题求助

问题:API解析JSON后调用getStandings()返回空数组

我尝试从API解析JSON对象,已在单独文件中定义JSON结构。解析器可成功解析JSON,但在viewDidLoad()中调用getStandings()函数时返回空数组。我是新手,试过类似问题的解决方案但无效,以下是我的JSON结构定义和请求解析代码,希望有人指出错误并说明修改方向:

JSON结构定义

struct FootballData : Codable{
    let response: [Response]
}

struct Response: Codable {
    let league: League
}

struct League: Codable {
    let id: Int
    let name: String
    let country: String
    let standings : [[Standings]]
}

struct Standings: Codable {
    let rank: Int
    let team: Team
    let points: Int
    let goalsDiff: Int
    let all: All
}

struct Team: Codable {
    let id: Int
    let name: String
    let logo: String
}

struct All: Codable {
    let played: Int
    let win: Int
    let draw: Int
    let lose: Int
}

请求解析代码

func getStandings() -> [[Standings]]{
    let standings = [[Standings]]()
    var request = URLRequest(url: URL(string: "https://v3.football.api-sports.io/standings?league=39&season=2022")!,timeoutInterval: Double.infinity)
    request.addValue("639248abcf96cbcebd90cd66aec49db4", forHTTPHeaderField: "x-rapidapi-key")
    request.addValue("v3.football.api-sports.io", forHTTPHeaderField: "x-rapidapi-host")
    request.httpMethod = "GET"
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if error == nil && data != nil {
            let decoder = JSONDecoder()
            do {
                let decodedData = try decoder.decode(FootballData.self, from: data!)
                let standings = decodedData.response[0].league.standings
                print(standings)
            } catch {
                print(error)
            }
        }
    }
    //4. Start the task
    task.resume()
    return standings
}

问题原因与修改方案

核心错误

URLSession.dataTask是异步执行的网络请求,你调用task.resume()后立刻返回了函数开头定义的空数组standings,此时网络请求还在后台运行,异步闭包里的解析结果根本无法同步影响返回值。另外,闭包里的let standings是局部变量,和函数外层的空数组完全无关,就算解析成功也不会改变返回值。

修改方案:改用闭包回调返回结果

异步操作无法通过同步返回值的方式获取结果,必须用闭包回调来传递解析后的结果或错误:

修改后的getStandings函数

func getStandings(completion: @escaping ([[Standings]]?, Error?) -> Void) {
    guard let url = URL(string: "https://v3.football.api-sports.io/standings?league=39&season=2022") else {
        completion(nil, NSError(domain: "URLError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无效的URL"]))
        return
    }
    
    var request = URLRequest(url: url, timeoutInterval: Double.infinity)
    request.addValue("639248abcf96cbcebd90cd66aec49db4", forHTTPHeaderField: "x-rapidapi-key")
    request.addValue("v3.football.api-sports.io", forHTTPHeaderField: "x-rapidapi-host")
    request.httpMethod = "GET"
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        // 优先处理错误
        if let error = error {
            completion(nil, error)
            return
        }
        
        // 验证数据是否存在
        guard let data = data else {
            completion(nil, NSError(domain: "DataError", code: 0, userInfo: [NSLocalizedDescriptionKey: "未获取到有效数据"]))
            return
        }
        
        // 解析JSON
        let decoder = JSONDecoder()
        do {
            let decodedData = try decoder.decode(FootballData.self, from: data)
            let standings = decodedData.response[0].league.standings
            completion(standings, nil)
        } catch {
            completion(nil, error)
        }
    }
    task.resume()
}

在viewDidLoad中的调用方式

override func viewDidLoad() {
    super.viewDidLoad()
    
    getStandings { standings, error in
        if let error = error {
            print("请求失败:\(error.localizedDescription)")
            return
        }
        
        guard let standings = standings else {
            print("未获取到排名数据")
            return
        }
        
        // 注意:更新UI必须切换到主线程
        DispatchQueue.main.async {
            // 这里处理获取到的排名数据,比如刷新表格视图
            print(standings)
        }
    }
}

额外注意事项

  • 所有UI操作必须在主线程执行,所以在闭包里处理UI时要加上DispatchQueue.main.async。
  • 代码中增加了URL有效性检查和数据存在性验证,避免强制解包导致崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:50:44