获取 WeatherKit 的当前天气、分钟级、小时级和每日预报;天气警报;iOS 18+ 的变化、历史对比、摘要和统计信息;以及必需的 Apple Weather 署名。在集成天气数据、显示预报或警报、缓存 WeatherKit 响应、显示署名或审查 iOS 应用中的 WeatherKit 查询限制时使用。
WeatherKit
使用 WeatherService 获取当前天气状况、小时级和每日预报、天气警报以及历史统计数据。显示必需的 Apple Weather 署名。
目录
设置
项目配置
- 在 Xcode 中启用 WeatherKit 能力(添加授权)
- 在 Apple Developer 门户中为你的 App ID 启用 WeatherKit
- 如果使用设备位置,在 Info.plist 中添加
NSLocationWhenInUseUsageDescription - WeatherKit 需要有效的 Apple Developer Program 会员资格
导入
import WeatherKit
import CoreLocation
创建服务
使用共享单例或创建实例。WeatherService 符合 Sendable;将应用缓存和 UI 状态单独隔离。
let weatherService = WeatherService.shared
// 或
let weatherService = WeatherService()
获取当前天气
获取某个位置的当前天气状况。返回一个包含所有可用数据集的 Weather 对象。
WeatherKit 温度是 Measurement<UnitTemperature> 值;使用 .formatted() 显示它们,以便单位和数字格式遵循用户的语言环境。
func fetchCurrentWeather(for location: CLLocation) async throws -> CurrentWeather {
let weather = try await weatherService.weather(for: location)
return weather.currentWeather
}
// 使用结果
func displayCurrent(_ current: CurrentWeather) {
let temp = current.temperature // Measurement<UnitTemperature>
let condition = current.condition // WeatherCondition 枚举
let symbol = current.symbolName // SF Symbol 名称
let humidity = current.humidity // Double (0-1)
let wind = current.wind // Wind (速度、方向、阵风)
let uvIndex = current.uvIndex // UVIndex
print("\(condition): \(temp.formatted())")
}
预报
小时级预报
默认返回从当前小时开始的连续 25 小时。
func fetchHourlyForecast(for location: CLLocation) async throws -> Forecast<HourWeather> {
let weather = try await weatherService.weather(for: location)
return weather.hourlyForecast
}
// 遍历小时
for hour in hourlyForecast {
print("\(hour.date): \(hour.temperature.formatted()), \(hour.condition)")
}
每日预报
默认返回从今天开始的连续 10 天。
func fetchDailyForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let weather = try await weatherService.weather(for: location)
return weather.dailyForecast
}
// 遍历天数
for day in dailyForecast {
print("\(day.date): \(day.lowTemperature.formatted()) - \(day.highTemperature.formatted())")
print(" 状况: \(day.condition), 降水概率: \(day.precipitationChance)")
}
自定义日期范围
使用 WeatherQuery 请求特定日期范围的预报。
每日和小时级日期范围查询使用包含的 startDate 和不包含的 endDate。它们可以包含自 2021 年 8 月 1 日以来的历史数据。预报最多可提供未来 10 天;每次请求最多返回 10 天的每日预报或约 240 小时的小时级预报。
func fetchExtendedForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let startDate = Date.now
let endDate = Calendar.current.date(byAdding: .day, value: 10, to: startDate)!
let forecast = try await weatherService.weather(
for: location,
including: .daily(startDate: startDate, endDate: endDate)
)
return forecast
}
对于针对明天的具体指导,请求本地明天的日期区间,而不是使用分钟级预报:
func fetchTomorrowForecast(for location: CLLocation) async throws -> Forecast<DayWeather> {
let calendar = Calendar.current
let tomorrow = calendar.startOfDay(
for: calendar.date(byAdding: .day, value: 1, to: .now)!
)
let dayAfterTomorrow = calendar.date(byAdding: .day, value: 1, to: tomorrow)!
return try await weatherService.weather(
for: location,
including: .daily(startDate: tomorrow, endDate: dayAfterTomorrow)
)
}
天气警报
获取某个位置的活跃天气警报。警报包括严重程度、摘要和受影响区域。
func fetchAlerts(for location: CLLocation) async throws -> [WeatherAlert]? {
let weather = try await weatherService.weather(for: location)
return weather.weatherAlerts
}
// 处理警报
if let alerts = weatherAlerts {
for alert in alerts {
print("警报: \(alert.summary)")
print("严重程度: \(alert.severity)")
print("区域: \(alert.region ?? "未知区域")")
print("详情: \(alert.detailsURL)") // 非可选,署名必需
}
}
对于警报仪表板,在讨论支持检查时明确命名 WeatherAvailability:它只暴露 alertAvailability 和 minuteAvailability,而不是当前、小时级或每日天气的广泛可用性矩阵。
选择性查询
只获取所需的数据集,以最小化 API 使用量和响应大小。每个 WeatherQuery 类型对应一个数据集。
单个数据集
let current = try await weatherService.weather(
for: location,
including: .current
)
// current 是 CurrentWeather
多个数据集
let (current, hourly, daily) = try await weatherService.weather(
for: location,
including: .current, .hourly, .daily
)
// current: CurrentWeather, hourly: Forecast<HourWeather>, daily: Forecast<DayWeather>
分钟级预报
在有限区域可用。返回未来一小时内以分钟为粒度的降水预报。
let minuteForecast = try await weatherService.weather(
for: location,
including: .minute
)
// minuteForecast: Forecast<MinuteWeather>? (不可用时为 nil)
可用查询类型
| 查询 | 返回类型 | 描述 |
|---|---|---|
.current |
CurrentWeather |
当前观测状况 |
.hourly |
Forecast<HourWeather> |
从当前小时开始的 25 小时 |
.daily |
Forecast<DayWeather> |
从今天开始的 10 天 |
.minute |
Forecast<MinuteWeather>? |
下一小时降水(有限区域) |
.alerts |
[WeatherAlert]? |
活跃天气警报 |
.availability |
WeatherAvailability |
仅警报和分钟级预报可用性 |
.changes |
WeatherChanges? |
即将到来的显著天气变化 (iOS 18+) |
.historicalComparisons |
HistoricalComparisons? |
当前天气与历史平均值对比 (iOS 18+) |
上下文查询
对于 iOS 18+ 上的“明天异常”或“正在变化”功能,一起请求可选的 .changes 和 .historicalComparisons 结果:前者报告即将到来的显著变化,后者提供历史背景。
let (changes, comparisons) = try await weatherService.weather(
for: location,
including: .changes, .historicalComparisons
)
历史摘要和统计信息使用 WeatherService 方法,而不是 WeatherQuery。加载 references/weatherkit-patterns.md 以了解它们的元组顺序、API 和统计特定属性。
署名
Apple 要求使用 WeatherKit 的应用显示署名。这是法律要求。
获取署名
func fetchAttribution() async throws -> WeatherAttribution {
return try await weatherService.attribution
}
加载 references/weatherkit-patterns.md 以获取完整的 SwiftUI 署名视图和缓存集成。
署名属性
| 属性 | 用途 |
|---|---|
combinedMarkLightURL |
浅色背景的 Apple Weather 标志 |
combinedMarkDarkURL |
深色背景的 Apple Weather 标志 |
squareMarkURL |
方形 Apple Weather 标志 |
legalPageURL |
法律署名网页的 URL |
legalAttributionText |
当无法显示网页视图时的文本替代 |
serviceName |
天气数据提供商名称 |
可用性
检查某个位置的天气警报或分钟级预报数据是否可用。WeatherAvailability 仅报告警报和分钟级可用性;其他数据集(如当前天气)预计在地理位置上都受支持。
func checkAvailability(for location: CLLocation) async throws {
let availability = try await weatherService.weather(
for: location,
including: .availability
)
// 检查特定数据集可用性
if availability.alertAvailability == .available {
// 可以安全获取警报
}
if availability.minuteAvailability == .available {
// 该区域分钟级预报可用
}
}
常见错误
不要:发布时没有 Apple Weather 署名
在显示 WeatherKit 数据的任何地方显示适当的 Apple Weather 标志并链接 legalPageURL;仅在无法显示法律页面时使用 legalAttributionText。
不要:只需要当前天气状况时获取所有数据集
每个数据集查询都会计入你的 API 配额。使用选择性查询中显示的选择性查询,只获取 UI 显示所需的数据。
不要:忽略分钟级预报的不可用性
分钟级预报在不支持的区域是可选的。检查可用性并处理 nil 结果,而不是强制解包。
不要:忘记 WeatherKit 授权
如果没有启用该能力,WeatherService 调用会在运行时抛出错误。
// 错误:未配置 WeatherKit 能力
let weather = try await weatherService.weather(for: location) // 抛出错误
// 正确:在 Xcode 的 Signing & Capabilities 中启用 WeatherKit
// 并在 Apple Developer 门户中为你的 App ID 启用
不要:不缓存就重复请求
WeatherKit 模型包含 metadata.expirationDate。将响应缓存到该过期时间,而不是自行设定固定间隔或在每次视图出现时获取。让模型或缓存拥有 loadIfNeeded;完整的 actor 模式在 references/weatherkit-patterns.md 中。
审查清单
- [ ] 在 Xcode 和 Apple Developer 门户中启用了 WeatherKit 能力
- [ ] 有效的 Apple Developer Program 会员资格(WeatherKit 必需)
- [ ] 在显示天气数据的任何地方显示了 Apple Weather 署名
- [ ] 署名标志使用了正确的配色方案变体(浅色/深色)
- [ ] 链接了法律署名页面或显示了
legalAttributionText - [ ] 只获取了所需的
WeatherQuery数据集(不需要时不要使用完整的weather(for:)) - [ ] 分钟级预报作为可选处理(在不支持的区域为 nil)
- [ ] 在遍历前检查天气警报是否为 nil
- [ ] 警报详情链接使用非可选的
detailsURL;可选的region是 nil 安全的 - [ ] 响应缓存到每个模型的
metadata.expirationDate - [ ]
WeatherAvailability用于警报/分钟级可用性,而不是作为广泛的支持矩阵 - [ ] 在将
CLLocation传递给服务之前请求了位置权限 - [ ] 温度和测量值使用
Measurement.formatted()进行格式化以适配语言环境
参考资料
- 扩展模式(SwiftUI 仪表板、图表集成、历史统计):references/weatherkit-patterns.md
- WeatherKit 框架
- WeatherService
- WeatherAttribution
- WeatherQuery
- WeatherQuery.daily(startDate:endDate:)
- WeatherQuery.hourly(startDate:endDate:)
- CurrentWeather
- CurrentWeather.temperature
- Measurement.formatted()
- Forecast
- HourWeather
- DayWeather
- WeatherAlert
- WeatherAvailability
- WeatherMetadata.expirationDate
- WeatherQuery.changes
- WeatherQuery.historicalComparisons
- WeatherKit 更新
- 为今天的天气带来上下文
- 使用 WeatherKit 获取天气预报






