What's new in HealthKit
Health & Fitness 进阶 20m

HealthKit 的新功能

What's new in HealthKit

2022年6月6日

在 Apple 官方观看视频

一句话判断

HealthKit 今年有三个实质性更新:睡眠阶段追踪、Swift async 查询 API、以及多活动运动记录——如果你的应用涉及健康数据,这三个功能都值得立即采用。

这场 Session 讲了什么

HealthKit 工程师 Karim 介绍了 iOS 16 和 watchOS 9 中 HealthKit 的四大更新:睡眠阶段追踪、Swift async 查询 API、多活动运动(如铁人三项)的增强表示、以及视力处方的数字存储。

Apple Watch 现在会自动追踪睡眠的不同阶段(REM、核心、深度),数据通过 HealthKit 对第三方应用开放。查询 API 全面支持 Swift async/await,大幅简化了代码。运动 API 新增了 HKWorkoutActivity 概念,允许在一次运动中记录多个不同的活动类型。

值得深挖的点

睡眠阶段的分类。 HealthKit 新增三种睡眠阶段:asleepCore(对应 AASM 分期模型的 1-2 期)、asleepDeep(对应 3 期)、asleepREM(快速眼动期)。原来的 asleep 被重命名为 asleepUnspecified,表示已入睡但未指定阶段。保存时每个连续的睡眠阶段应创建一个独立的样本。

Swift async 查询的简洁语法。 每个 HKQuery 现在都有对应的 QueryDescriptor。获取初始结果用 result(for:),监听持续更新用 results(for:) 返回 AsyncSequence。代码量相比闭包回调方式显著减少,而且可以用 try/catch 处理错误。

多活动运动的 HKWorkoutActivity。 一次运动(如铁人三项)可以包含多个 HKWorkoutActivity,每个活动有自己的类型、时间范围和统计数据。活动之间不能重叠,但不需要连续——过渡期可以用 transition 类型的活动单独记录。

视力处方。 HealthKit 现在支持保存视力处方的数字副本,包括镜片度数、散光等参数。

代码片段

import HealthKit

// 读取特定睡眠阶段的数据
let sleepStagePredicate = HKQuery.predicateForSamples(
    with: .asleepREM  // 筛选 REM 阶段
)
let queryPredicate = HKQuery.predicateForSamples(
    with: .sleepAnalysis,
    operator: .equalTo,
    value: sleepStagePredicate
)

// 如果要读取所有睡眠阶段,使用新的 .allAsleepValues
let allSleepPredicate = HKQuery.predicateForSamples(
    with: .sleepAnalysis,
    operator: .equalTo,
    value: .allAsleepValues
)

// 使用 Swift async 查询获取统计数据
let descriptor = HKStatisticsCollectionQueryDescriptor(
    predicate: HKSamplePredicate.sample(
        type: .quantityType(forIdentifier: .activeEnergyBurned)!
    ),
    options: .cumulativeSum,
    anchorDate: thisSunday,
    intervalComponents: DateComponents(weekOfYear: 1)
)

// 获取一次性快照
let statsCollection = try await descriptor.result(for: healthStore)

// 或持续监听更新
for try await result in descriptor.results(for: healthStore) {
    // 实时更新卡路里数据
    updateUI(with: result)
}

// 记录多活动运动
let workoutConfig = HKWorkoutConfiguration()
workoutConfig.activityType = .swimBikeRun  // 铁人三项
let session = try HKWorkoutSession(healthStore: healthStore, configuration: workoutConfig)
let builder = session.associatedWorkoutBuilder

// 开始运动
session.startActivity()
try await builder.beginCollection()

// 添加游泳活动
let swimActivity = HKWorkoutActivity(
    workoutConfiguration: swimConfig,
    start: swimStart,
    end: swimEnd
)
try await builder.addWorkoutActivity(swimActivity)

最佳实践

  • 每个连续的睡眠阶段创建独立的 sleepAnalysis 样本
  • 如果你的应用之前使用 .asleep 读取睡眠数据,迁移到 .allAsleepValues 以包含新的阶段数据
  • 使用 Swift async QueryDescriptor 替代旧的闭包回调查询,代码更清晰
  • 多活动运动中,过渡期可以用 transition 类型单独记录
  • 运动活动之间不能时间重叠,但可以不连续
  • 在 watchOS 上使用 HKWorkoutSession 的 beginNewActivity 方法切换活动

还有什么值得关注

  • 睡眠阶段数据由 Apple Watch 自动收集,应用可以直接读取
  • 视力处方的数字存储为健康管理应用提供了新的数据维度
  • HKWorkoutActivity 的统计数据可以按单个活动分析,不再只能看整次运动的汇总
  • Swift async 支持从 iOS 15.4 开始可用,旧系统仍需使用闭包方式
WWDC 2022