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

iOS WeatherKit获取逐小时预报为空,请求技术协助

解决WeatherKit获取逐小时预报为空的问题

问题描述

我已经通过以下代码成功获取当前天气状况:

var weatherDescription: String {
  let description = weather?.currentWeather.condition.description ?? "Loading..."
  return description
}

但尝试获取逐小时预报并打印时,结果为空:

var hourlyWeatherForecast: Forecast<HourWeather> {
  let forecast = (weather?.hourlyForecast)! //TODO: handle error case
  print (forecast)
  return forecast
}

我是基础薄弱的业余程序员,恳请帮助!

以下是该类的完整代码:

//
//  WeatherKitManager.swift
//  FranzFahrenheitv2
//
//  Created by Björn Schefzyk on 3/25/23.
//

import Foundation
import WeatherKit

@MainActor class WeatherKitManager: ObservableObject {
    
    @Published var weather: Weather?
    
    func getWeather(latitude: Double, longitude: Double) async {
        do {
            weather = try await Task.detached(priority: .userInitiated) {
                return try await WeatherService.shared.weather(for: .init(latitude: latitude, longitude: longitude))
            }.value
            //print("Weather: \(String(describing: weather))")
        } catch {
            fatalError("\(error)")
        }
    }
    
    var symbol: String {
        weather?.currentWeather.symbolName ?? "xmark"
    }
    
    var tempC: String {
        let temp =
        Int(weather?.currentWeather.temperature.value ?? 0)
        let convert = String(temp) + "°C"
        return convert
    }
    
    var tempF: String {
        let temp =
        Int(weather?.currentWeather.temperature.converted(to: .fahrenheit).value ?? 0)
        let convert = String(temp) + "°F"
        return convert
    }
    
    var weatherDescription: String {
        let description = weather?.currentWeather.condition.description ?? "Loading..."
        return description
    }
    
    var hourlyWeatherForecast: Forecast<HourWeather> {
        let forecast = (weather?.hourlyForecast)! //TODO: handle error case
        print (forecast)
        return forecast
    }
}

问题分析与解决步骤

1. 修复强制解包的风险

你当前用!强制解包weather?.hourlyForecast,如果weather未加载完成或获取失败,不仅会崩溃,还可能因解包时机错误拿到空值。先改成安全的可选绑定:

var hourlyWeatherForecast: Forecast<HourWeather>? {
    guard let forecast = weather?.hourlyForecast else {
        print("逐小时预报未加载或获取失败")
        return nil
    }
    print(forecast)
    return forecast
}

2. 显式指定WeatherKit请求的预报类型

虽然默认请求会包含逐小时数据,但显式指定可确保获取到目标数据,避免遗漏:
修改getWeather方法:

func getWeather(latitude: Double, longitude: Double) async {
    do {
        let weatherService = WeatherService.shared
        // 明确指定获取当前天气和逐小时预报
        let weather = try await weatherService.weather(
            for: .init(latitude: latitude, longitude: longitude),
            including: [.current, .hourly]
        )
        self.weather = weather
        print("完整Weather数据:\(weather)") // 打印完整数据确认是否包含hourlyForecast
    } catch {
        print("获取天气失败:\(error)")
        self.weather = nil // 替换fatalError,避免程序直接崩溃
    }
}

3. 确保打印时机正确

hourlyWeatherForecast是计算属性,只有被访问时才会执行打印。如果在weather未加载完成时访问,自然拿到空值。要在weather加载完成后再访问它,比如在View中这样使用:

struct ContentView: View {
    @StateObject private var weatherManager = WeatherKitManager()
    
    var body: some View {
        VStack {
            if let hourlyForecast = weatherManager.hourlyWeatherForecast {
                Text("逐小时预报数量:\(hourlyForecast.forecast.count)")
                // 遍历显示每小时数据
                ForEach(hourlyForecast.forecast, id: \.date) { hour in
                    Text("\(hour.date.formatted(.dateTime.hour())): \(hour.temperature.value.formatted())°C")
                }
            } else {
                Text("加载中...")
            }
        }
        .task {
            await weatherManager.getWeather(latitude: 37.334722, longitude: -122.008889) // 替换为你的目标坐标
        }
    }
}

4. 优化Forecast对象的打印方式

直接打印Forecast对象会因为默认描述不够详细,看起来像空值。可以打印其内部的forecast数组查看具体数据:

var hourlyWeatherForecast: Forecast<HourWeather>? {
    guard let forecast = weather?.hourlyForecast else {
        print("逐小时预报未加载")
        return nil
    }
    print("逐小时预报数量:\(forecast.forecast.count)")
    print("第一个小时数据:\(forecast.forecast.first ?? "无数据")")
    return forecast
}

内容的提问来源于stack exchange,提问作者Björn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:22:42