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

SwiftUI中Open-Meteo天气数据无法显示问题求助

问题解决:天气数据无法在SwiftUI界面显示

核心问题总结

你的代码能打印数据但界面不显示,主要是这几个问题:

  • 解析后的数据没传递给视图的状态变量
  • 视图里用数组存储单个对象,遍历空数组自然没内容
  • 网络请求线程没切回主线程,UI更新不生效
  • Service和视图之间没有绑定监听

分步修改代码

1. 修复WeatherService(数据获取层)

删掉内部循环引用的代码,添加@Published属性存储数据,并且强制在主线程更新UI:

import Foundation

class WeatherService : ObservableObject{
    let urlapi = "https://api.open-meteo.com/v1/forecast?latitude=52.40&longitude=13.07&daily=weathercode,temperature_2m_max,temperature_2m_min&current_weather=true&past_days=1&timezone=Europe%2FBerlin"
    
    // 用@Published让视图监听数据变化
    @Published var weatherData: WeatherModel?

    func getDate(){
        guard let url = URL(string: urlapi) else {
            print("URL无效")
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let data = data, error == nil else{
                print("请求出错: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            do {
                let result = try JSONDecoder().decode(WeatherModel.self, from: data)
                print(result)
                // 切回主线程更新UI
                DispatchQueue.main.async {
                    self?.weatherData = result
                }
            } catch {
                print("解析错误: \(error.localizedDescription)")
                print(String(describing: error))
            }
        }.resume()
    }
}

2. 修复ContentView(视图层)

改用@StateObject持有Service实例,直接使用单个WeatherModel对象,调整UI显示当前气温和未来7天的高低温:

import SwiftUI

struct ContentView: View {
    // 用StateObject创建Service实例,生命周期和视图绑定
    @StateObject private var weatherService = WeatherService()

    var body: some View {
        VStack(spacing: 20) {
            // 显示当前气温
            if let currentWeather = weatherService.weatherData?.currentWeather {
                Text("当前气温: \(currentWeather.temperature)°C")
                    .font(.title)
            } else {
                Text("加载中...")
            }
            
            // 显示未来7天的高低温(跳过第一天的历史数据)
            Text("未来7天预报")
                .font(.headline)
            
            if let dailyData = weatherService.weatherData?.daily {
                // 从索引1开始,跳过past_days返回的历史数据
                ForEach(1..<dailyData.time.count, id: \.self) { index in
                    HStack {
                        Text(dailyData.time[index])
                        Spacer()
                        Text("最高: \(dailyData.temperature2MMax[index])°C")
                        Spacer()
                        Text("最低: \(dailyData.temperature2MMin[index])°C")
                    }
                    .padding(.horizontal)
                }
            }
        }
        .onAppear(){
            weatherService.getDate()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

3. WeatherModel(模型层)

你的模型解析是正常的,不需要修改,如果想优化可以去掉不需要的Identifiable(因为Daily里的数组遍历用索引就够),但当前代码不影响功能:

import Foundation

struct WeatherModel: Decodable, Identifiable {
    var id = UUID()
    let currentWeather: CurrentWeather
    let daily: Daily

    enum CodingKeys: String, CodingKey {
        case currentWeather = "current_weather"
        case daily
    }
}

struct CurrentWeather: Decodable {
    let temperature: Double
    let isDay: Int
    let time: String

    enum CodingKeys: String, CodingKey {
        case temperature
        case isDay = "is_day"
        case time
    }
}

struct Daily: Decodable {
    let time: [String]
    let temperature2MMax, temperature2MMin: [Double]

    enum CodingKeys: String, CodingKey {
        case time
        case temperature2MMax = "temperature_2m_max"
        case temperature2MMin = "temperature_2m_min"
    }
}

为什么这样改?

  • @Published + @StateObject让视图能自动监听Service里的数据变化,数据更新时UI自动刷新
  • 切回主线程是因为SwiftUI只能在主线程更新UI,后台线程的修改不会触发界面刷新
  • 接口返回的是单个WeatherModel对象,所以不需要用数组存储,直接用可选类型处理加载状态
  • 跳过daily数组的第一个元素,因为你请求了past_days=1,第一个是历史数据,我们要的是未来7天

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:22:15