HealthKit 的新功能
What's new in HealthKit
2022年6月6日
一句话判断
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 开始可用,旧系统仍需使用闭包方式