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

无法从Weather API获取数据——Swift/JSON开发问题

天气API数据获取失败的问题排查与修复

核心问题分析

  • 解码对象错误:weatherapi返回的JSON结构外层是包含current字段的对象,你直接解码Current类型导致解码失败。
  • 错误处理缺失细节:catch块仅打印"failed",无法定位具体错误原因(如解码错误、网络错误)。
  • API密钥未替换:URL中的APIKEY是占位符,必须替换为你在weatherapi.com申请的真实密钥。

修复后的代码

1. WeatherViewModel 修正

class WeatherViewModel: ObservableObject {
    
    @Published var tempC: String = "-"
    @Published var gustMph: String = "-"
    @Published var errorMessage: String? // 新增错误提示
    
    init() {
        fetchWeather()
    }
    
    func fetchWeather() {
        // 替换为你的真实API密钥
        guard let url = URL(string: "https://api.weatherapi.com/v1/current.json?key=你的真实API密钥&q=London&aqi=no") else {
            DispatchQueue.main.async {
                self.errorMessage = "无效的请求地址"
            }
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            // 处理网络错误
            if let error = error {
                DispatchQueue.main.async {
                    self.errorMessage = "网络请求失败: \(error.localizedDescription)"
                }
                return
            }
            
            // 验证HTTP响应状态码
            guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
                DispatchQueue.main.async {
                    self.errorMessage = "服务器返回错误状态码"
                }
                return
            }
            
            // 处理数据为空的情况
            guard let data = data else {
                DispatchQueue.main.async {
                    self.errorMessage = "未获取到数据"
                }
                return
            }
            
            // 解码数据(外层是Weather对象,不是Current)
            do {
                let weatherModel = try JSONDecoder().decode(Weather.self, from: data)
                DispatchQueue.main.async {
                    self.tempC = "\(weatherModel.current.tempC)°C"
                    self.gustMph = "\(weatherModel.current.gustMph) mph"
                    self.errorMessage = nil
                }
            } catch {
                DispatchQueue.main.async {
                    self.errorMessage = "数据解析失败: \(error.localizedDescription)"
                }
                print("解码错误详情: \(error)") // 控制台打印详细错误
            }
        }
        task.resume()
    }
}

2. ContentView 优化(添加错误提示)

struct ContentView: View {
    @StateObject var viewModel = WeatherViewModel()
    
    var body: some View {
        NavigationView {
            VStack(spacing: 30) {
                Text(viewModel.tempC)
                    .font(.system(size: 50))
                Text(viewModel.gustMph)
                    .font(.system(size: 30))
                
                // 显示错误信息
                if let errorMsg = viewModel.errorMessage {
                    Text(errorMsg)
                        .foregroundColor(.red)
                        .padding(.top, 20)
                }
            }
            .navigationTitle("Weather Test")
            .padding()
        }
    }
}

3. 结构体保持不变(原定义符合接口返回结构)

struct Weather: Codable {
    let current: Current
}

struct Current: Codable {
    let tempC: Int
    let tempF: Double
    let gustMph: Double
    let gustKph: Int

    enum CodingKeys: String, CodingKey {
        case tempC = "temp_c"
        case tempF = "temp_f"
        case gustMph = "gust_mph"
        case gustKph = "gust_kph"
    }
}

额外注意事项

  • 确保API密钥已正确替换,且账户有足够的请求额度。
  • 测试设备网络连接,确认能正常访问weatherapi接口。
  • 可直接在浏览器中访问请求URL,验证返回的JSON结构是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:13:26