Bring context to today's weather
System Frameworks 进阶 20m

让天气数据更有意义:WeatherKit 上下文增强

Bring context to today's weather

2024年6月10日

在 Apple 官方观看视频

一句话判断

WeatherKit 今年新增了天气变化预警和历史对比两个查询,你的 app 终于可以不只是”展示数据”,而是”告诉你数据意味着什么”。

这场 Session 讲了什么

WeatherKit 是 Apple Weather Service 对外暴露的 API 层,支撑着 Apple 自家的天气 app,也被 Carrot Weather、(Not Boring) Weather、DuckDuckGo 等第三方 app 使用。它提供 Swift 和 REST 两种 API 形态,覆盖了当前天气、逐分钟降水、逐小时和逐日预报、天气预警等核心数据集。今年它迎来了三方面增强:更细粒度的预报数据、天气变化上下文提示、以及二进制数据传输格式。

预报数据变细了——current conditions 和 hourly forecast 现在可以返回按高度分层的云量(cloud cover by altitude),hourly 还能返回逐小时降水量(precipitation amount),daily forecast 拆分了白天和夜间的天气(day parts),还能返回高低温湿度。这些都是 Apple Weather app 已经在用的数据,现在你也能拿到了。

但最有价值的更新是两个全新的查询类型。Changes 查询告诉你接下来温度和降水会发生什么显著变化,以及变化发生的时间。Historical Comparisons 查询把今天的天气和过去 50 多年的历史均值做对比,按偏差程度排序。这两个查询让你的 app 从”展示数字”进化到”解读数字”——用户不需要自己对比昨天和今天的温度,你的 app 直接告诉他”明天气温会骤降 8 度”。

Session 的演示者反复强调了一个设计理念:天气 app 的竞争力不在于数据的广度,而在于你能否把原始数据转化成对用户有意义的判断。这和苹果自家 Weather app 的演进方向一致——从最初的”温度+湿度”看板,到现在集成变化预警、历史对比、空气质量指数等上下文信息。WeatherKit 的这些新 API 让第三方 app 也能做到同样的事。

值得深挖的点

Changes 查询:主动推送天气转折点

Changes 查询返回的是一个变化事件列表,每个事件包含起止时间和变化类型(increase、decrease 或 steady)。苹果的天气 app 已经在用它来高亮显示即将到来的温度变化。你也可以做同样的事——不需要自己写逻辑去对比逐小时预报找出转折点,WeatherKit 直接把结论给你。Changes 查询在 Swift 端通过 .changes 传递给 weather API,在 REST 端对应 weatherChanges dataset。返回结果中每个 change 对象都有 startDate、endDate 和 changeType 字段,你可以直接用来驱动 UI 更新。

这个设计的价值在于:天气 app 的核心体验不是展示数据表格,而是回答”我今天需要带伞吗”、“明天穿什么”这样的实际问题。Changes 查询把”数据→判断”这步推理从用户脑中转移到了服务端。你拿到的是一个结构化的结论,直接展示给用户就行。

值得注意的是,这个查询即使没有显著变化也会返回结果(告诉你”天气平稳”)。这意味着你不需要特殊处理”无数据”的情况,UI 逻辑更简洁。

Historical Comparisons:50 年数据的”异常检测”

这个查询把当前天气和过去 50 多年的历史均值做对比,返回按偏差显著程度排序的结果列表。第一个元素就是”今天最不正常的那个指标”。比如今天最高温度比历史均值高了 5 度,这就是一个高偏差项。

这种数据的叙事价值远大于数据本身。“今天比往年热 5 度”比”今天 32 度”更能引起用户注意。如果你在做天气 app,这个 API 能让你的 UI 从平铺直叙变成有故事性的——用户不只是在看数字,而是在理解”今天的天气在历史上意味着什么”。Session 的演示者提到,苹果自家的 Weather app 就在用这个查询来展示”今日最高温度与历史均值的偏差”。这种信息在用户心中留下的印象远比原始温度数字深刻得多。

REST API 返回的数据结构很直观:每个 comparison 包含当前值、历史均值、偏差值。按显著性排序意味着你只需要取第一个元素就能展示”今日最值得关注的天气异常”。

另外值得一提的是新增的按高度分层的云量数据。以前你只能拿到一个整体的 cloud cover 百分比,现在 current conditions 和 hourly forecast 都支持返回不同高度的云量分布。这对航空、户外运动、摄影等细分场景很有价值——低空云层和高空卷云对飞行和拍照的影响完全不同。daily forecast 的新 day parts 功能让你可以分别获取白天和夜间的预报,不再只用全天均值糊弄,这对”上午晴下午雨”这种场景的展示准确性提升很大。

代码片段

获取逐小时降水量

extension CLLocation {
    static let newYork = CLLocation(latitude: 40.7128, longitude: -74.0060)
}

let weather = try await WeatherService().weather(
    for: .newYork,
    query: [.hourly]
)

// 直接访问逐小时降水量
let hourlyRain = weather.hourlyForecast?
    .map { $0.precipitationAmount }

场景:展示今天每小时降水量。坑:precipitationAmount 的单位取决于 locale 设置,显示前做一下单位换算。

查询明天的温度变化

let weather = try await WeatherService().weather(
    for: .newYork,
    query: [.changes]
)

// 筛选明天发生的低温下降
let tomorrowDrops = weather.weatherChanges?.changes
    .filter { $0.startDate.isTomorrow }
    .filter { $0.changeType == .decrease }

if let drop = tomorrowDrops?.first {
    // "明天最低气温将下降,注意保暖"
    showTemperatureAlert(drop)
}

场景:主动提醒用户即将到来的温度变化。坑:changes 查询始终返回数据(即使只有 steady 状态),做 UI 时要处理”无显著变化”的情况。

REST API 获取历史对比

GET https://weatherkit.apple.com/v2/weather/en-US/40.7128/-74.0060
    ?dataSets=historicalComparisons
    &hourlyStart=currentHour
{
  "historicalComparisons": [
    {
      "type": "highTemperature",
      "currentValue": 32,
      "historicalAverage": 27,
      "deviation": 5
    }
  ]
}

场景:展示”今天比往年热多少”。坑:需要生成 authentication bearer token 才能访问 API,token 过期时间较短,建议用缓存机制。

最佳实践

新项目:从一开始就把 Changes 和 Historical Comparisons 集成到天气展示流程中。不要只做一个”数字看板”,要做”天气解读器”。用 Changes 在首页展示即将到来的天气转折,用 Historical Comparisons 为每日天气添加上下文。

已有项目:如果你已经在用 WeatherKit,升级成本很低。新增的 precipitationAmountcloudCoverByAltitude 等属性直接加在现有的 forecast 对象上,两个新查询类型和现有查询用法一致(Swift 端加个 .changes.historicalComparisons,REST 端加个 dataset 参数)。REST API 的 hourly forecast 默认返回 24 小时数据,但你也可以通过 hourlyStarthourlyEnd 参数请求最多 240 小时的预报。使用相对时间参数可以让 Apple Weather Service 根据传入的时区自动计算起止时间,非常方便。

还有什么值得关注

  • WeatherKit 现在支持二进制数据传输格式(binary format),可以减少网络传输量,对频繁更新天气数据的场景有帮助。
  • Daily forecast 的新 day part 拆分意味着你可以分别展示白天和夜间的天气,不再只能用全天均值。
  • 所有新功能在 REST API 和 Swift API 上都同时可用,接口设计保持一致。
WWDC 2024