关于 weatherkit
weatherkit 是面向 Swift 开发者的 WeatherKit 使用指南,可通过 WeatherService 获取天气数据并展示必需的 Apple 署名。内容涵盖选择性查询、数据可用性与响应缓存。
主要功能
- 01获取当前天气与预报
- 02读取警报和历史比较
- 03用 WeatherQuery 选择数据集
- 04检查分钟预报和警报可用性
- 05处理署名与响应缓存
适用场景
- 01在应用中显示当前天气
- 02构建逐小时或逐日预报视图
- 03显示地点天气警报
- 04将天气与历史平均值比较
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dpearson2699/ swift-ios-skills --skill weatherkit安装后在 Claude Code 中输入/weatherkit确认已加载。
附带文件evals/evals.jsonreferences/weatherkit-patterns.md
详细介绍
WeatherKit
使用 WeatherService 获取当前天气状况、逐小时和逐日预报、天气警报以及历史统计数据。请显示 Apple Weather 要求的署名信息。
目录
设置
项目配置
- 在 Xcode 中启用 WeatherKit 功能(会添加相应授权)
- 在 Apple Developer 门户中为你的 App ID 启用 WeatherKit
- 如果使用设备位置,请将
NSLocationWhenInUseUsageDescription添加到 Info.plist - 使用 WeatherKit 需要有效的 Apple Developer Program 会员资格
导入
import WeatherKit
import CoreLocation
创建服务
使用共享的单例或创建一个实例。WeatherService 遵循
Sendable;请单独隔离应用缓存和界面状态。
let weatherService = WeatherService.shared
// or
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
}
// Using the result
func displayCurrent(_ current: CurrentWeather) {
let temp = current.temperature // Measurement<UnitTemperature>
let condition = current.condition // WeatherCondition enum
let symbol = current.symbolName // SF Symbol name
let humidity = current.humidity // Double (0-1)
let wind = current.wind // Wind (speed, direction, gust)
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
}
// Iterate hours
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
}
// Iterate days
for day in dailyForecast {
print("\(day.date): \(day.lowTemperature.formatted()) - \(day.highTemperature.formatted())")
print(" Condition: \(day.condition), Precipitation: \(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
}
// Process alerts
if let alerts = weatherAlerts {
for alert in alerts {
print("Alert: \(alert.summary)")
print("Severity: \(alert.severity)")
print("Region: \(alert.region ?? "Unknown region")")
print("Details: \(alert.detailsURL)") // Non-optional and required for attribution
}
}
对于警报仪表板,在讨论支持情况检查时,请明确指出 WeatherAvailability:它仅提供 alertAvailability 和 minuteAvailability,而不提供当前、逐小时或逐日天气的综合可用性矩阵。
选择性查询
仅获取所需数据集,以尽量减少 API 用量和响应大小。每种 WeatherQuery 类型都对应一个数据集。
单个数据集
let current = try await weatherService.weather(
for: location,
including: .current
)
// current is 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 if unavailable)
可用的查询类型
| 查询 | 返回类型 | 说明 |
|---|---|---|
.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
)
// Check specific dataset availability
if availability.alertAvailability == .available {
// Safe to fetch alerts
}
if availability.minuteAvailability == .available {
// Minute forecast available for this region
}
}
常见错误
不要:未显示 Apple Weather 署名就发布
凡是显示 WeatherKit 数据的地方,都应显示适当的 Apple Weather 标志并链接到 legalPageURL;只有在无法显示法律页面时,才使用 legalAttributionText。
不要:只需要当前天气状况,却获取所有数据集
每次数据集查询都会占用 API 配额。请使用选择性查询中所示的查询,仅获取 UI 会显示的数据。
不要:忽略分钟级预报不可用的情况
在不支持的地区,分钟级预报可能不可用。请检查其可用性,并处理 nil 结果,而不要对其强制解包。
不要:忘记 WeatherKit 权限
如果未启用相应功能,WeatherService 调用会在运行时抛出错误。
// WRONG: No WeatherKit capability configured
let weather = try await weatherService.weather(for: location) // Throws
// CORRECT: Enable WeatherKit in Xcode Signing & Capabilities
// and in the Apple Developer portal for your 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 获取天气预报