WWDC Quick Look 💓 By SwiftGGTeam
Bring context to today's weather

Bring context to today's weather

观看原视频

Highlight

WeatherKit 新增 Changes 和 Historical Comparisons 两种查询,让你的天气 app 从”展示数字”进化到”解读天气变化”。


核心内容

打开一个天气 app,你看到的通常是温度、湿度、风速这些数字。用户需要自己做判断:今天比昨天冷吗?明天会不会突然降温?这种”让用户自己对比”的体验,其实是数据呈现的失败——app 手里有数据,但没有替用户完成解读。

今年 WeatherKit 的更新直接回应了这个痛点。新增的 Changes 查询返回即将到来的温度和降水变化,包含变化发生的时间窗口和变化方向(升高/降低/稳定)。Historical Comparisons 查询则把当前天气与过去 50 多年的历史均值做对比,结果按偏差程度排序。Apple 自家的 Weather app 已经在用这两个查询:Changes 用来在首页高亮”明天气温骤降”,Historical Comparisons 用来显示”今天高温比历史平均高 3°C”。

除了这两个新查询,预报数据本身也在变细。current conditions 和 hourly forecast 新增了按高度分层的云量(cloud cover by altitude),hourly 新增了逐小时降水量(precipitationAmount),daily forecast 可以按白天/夜间拆分(day parts),还能返回高低温湿度。这些数据 Apple Weather app 一直在用,现在第三方也能拿到了。REST API 端还新增了 FlatBuffers 二进制格式支持,比压缩 JSON 最高减少 25% 体积、90% 解析时间。

详细内容

逐小时降水量

Swift 端获取逐小时降水量只需指定 .hourly 查询,然后访问 precipitationAmount 属性(02:40):

let hourlyPrecipitation = try await WeatherService()
    .weather(for: .newYork, including: .hourly)
    .map(\.precipitationAmount)
  • WeatherService().weather(for:including:) 是 WeatherKit 的主查询入口,including 参数指定数据集
  • .hourly 请求逐小时预报,返回 HourlyForecast 数组
  • .map(\.precipitationAmount) 用 key path 直接提取每小时的降水量,跳过其他字段

REST 端等价写法(03:25):

https://weatherkit.apple.com/api/v2/weather/en-US/40.710/-74.006?dataSets=forecastHourly&relativeHourlyStart=0&relativeHourlyEnd=1&hourlyRelativeTo=now&timezone=America/New_York
  • dataSets=forecastHourly 指定请求逐小时预报
  • relativeHourlyStartrelativeHourlyEnd 用相对时间指定范围,Apple Weather Service 根据传入时区自动计算起止时间
  • 不指定范围时默认返回 24 小时,最多可请求 240 小时

Changes 查询

获取即将到来的天气变化(06:05):

let changes = try await WeatherService()
   .weather(for: .newYork, including: .changes)

let lowTemperatureChanges = changes?
   .filter(\.date.isTomorrow)
   .map(\.lowTemperature)

if let lowTemperatureChanges, lowTemperatureChanges.contains(.decrease) {
   // Lower temperatures expected tomorrow
}
  • .changes 是新增的查询类型,返回 WeatherChanges 对象
  • 每个 change 包含 startDateendDate 和变化类型(如 increasedecreasesteady
  • 上例筛选出明天发生的低温变化,如果包含 .decrease 则提示用户

REST 端只需 dataSets=weatherChanges06:43)。返回的每个 change 对象包含 startDateendDatetype(如 highTemperatureIncrease)。即使没有显著变化也会返回结果,typesteady

Historical Comparisons 查询

把今天天气和历史均值对比(08:17):

let mostSignificant = try await WeatherService()
    .weather(for: .newYork, including: .historicalComparisons)?
    .first

switch mostSignificant {
case .highTemperature(let trend), .lowTemperature(let trend):
    // Display temperature trend
    break
case .some, .none:
    break
}
  • .historicalComparisons 返回对比列表,按偏差显著程度排序
  • .first 取偏差最显著的那项
  • 每个对比包含 currentValue(当前值)、baselineValue(历史基准值)、deviationType(偏差等级:withinNormalRange/higher/muchHigher/lower/muchLower)和 baselineType(统计方法,目前为 mean

Statistics API:历史均值与每日摘要

全新的 Statistics API 提供两个查询。Historical Averages 返回自 1970 年以来的长期均值(月粒度示例,11:11):

let averagePrecipitation = try await WeatherService()
    .monthlyStatistics(
        for: .newYork,
        startMonth: 1,
        endMonth: 12,
        including: .precipitation
    )

let averagePrecipitationAmountsPerMonth = Dictionary(
    grouping: averagePrecipitation,
    by: \.month
)
  • monthlyStatistics 按月获取历史均值,月份编号 1-12
  • 返回结果按月分组,Apple Weather app 用此展示各月降水均值

Daily Summary 返回过去任一天的天气摘要(回溯至 2021 年 8 月 1 日)(12:52):

let pastThirtyDaysSummary = try await WeatherService()
    .dailySummary(
       for: .newYork,
       forDaysIn: DateInterval(start: .thirtyDaysAgo, end: .now),
       including: .precipitation
    )
    .first

if let pastThirtyDaysSummary {
    // We have a daily weather summary for each day in the past 30 days
}
  • dailySummary 接受日期区间,返回该区间内每天的摘要
  • 摘要包含高低温、降水量、降雪量
  • Apple Weather app 用此展示过去 30 天降水累积

FlatBuffers 二进制格式

REST API 新增 FlatBuffers 支持(14:16)。相比压缩 JSON,体积减少最高 25%,解析时间减少最高 90%。Swift API 自动享受此优化,REST 端需在请求头指定 Accept 即可激活。

核心启发

  • 做什么:在天气首页增加”即将变化”卡片。调用 Changes 查询,筛选未来 24-48 小时内的温度和降水变化,对包含 .increase.decrease 的条目用醒目样式展示。为什么值得做:用户打开天气 app 最关心的就是”明天和今天有什么不同”,这个卡片直接回答了这个问题。怎么开始:.changes 查询的返回值自带 startDatetype,前端只需做简单的过滤和渲染。

  • 做什么:为当日天气增加”比历史同期”标签。调用 Historical Comparisons 查询,取 deviationType 不为 withinNormalRange 的条目,展示”今天高温比历史均值高 3°C”之类的文案。为什么值得做:单独看 28°C 没有判断力,知道”这个月份平均 22°C”才有。怎么开始:.historicalComparisons 返回的每个对象都有 currentValuebaselineValue,做减法即可生成文案。

  • 做什么:旅行规划页面展示目的地各月降水均值。调用 Statistics API 的 monthlyStatistics,请求全年降水数据,用柱状图或日历热力图呈现。为什么值得做:用户规划旅行时需要知道目的地的雨季/旱季,这是纯预报数据做不到的。怎么开始:monthlyStatistics(for:startMonth:endMonth:including:) 一行调用,按月分组后直接喂给图表组件。

  • 做什么:REST API 接入 FlatBuffers 减少传输和解析开销。如果你的天气 app 后端频繁调用 WeatherKit REST API 获取大量历史数据,在请求头添加 FlatBuffers 的 Accept 即可。为什么值得做:数据量大的场景(如 30 天 daily summary)体积减少 25%、解析快 90%,用户体验直接提升。怎么开始:REST 请求头指定 FlatBuffers 格式,Swift API 端无需改动。

关联 Session

评论

GitHub Issues · utterances