CareKit 新特性概览
What's new in CareKit
2020年6月25日
一句话判断
CareKit 2.0 的架构重构让它从”黑盒框架”变成了真正的开发工具包——如果你在做健康类应用,这次升级值得关注。
这场 Session 讲了什么
CareKit 是 Apple 推出的开源框架,用于构建健康管理类应用。WWDC 2020 带来了 CareKit 的重大更新,核心变化是从以 View 为中心的封闭架构转向以数据模型驱动的开放架构。新版本引入了 OCKStore 作为统一的数据持久层,支持同步、查询和监听数据变更。
Session 详细介绍了新的数据模型层次:OCKTask 定义”要做什么”(如每日服药提醒),OCKOutcome 记录”做了什么”(如实际服药时间),OCKSchedule 控制”什么时候做”(如每天早中晚各一次)。这套模型设计清晰,覆盖了健康管理场景中的核心需求。重要的是,所有数据模型都遵循 Identifiable 协议,可以无缝集成到 SwiftUI 的声明式 UI 中。
另一个重大变化是 CareKit 现在完全基于 Swift Package Manager 分发,不再依赖 CocoaPods。框架内部也大量采用了 Swift 的特性,如 async/await 风格的回调处理和泛型约束。
值得深挖的点
OCKStore 与 HealthKit 的双向同步
CareKit 2.0 内置了与 HealthKit 的集成能力。你可以配置 OCKHealthKitStore 来自动将任务完成情况同步到 HealthKit,也可以从 HealthKit 读取数据作为 outcome 的来源。这意味着用户在 Apple Watch 上记录的步数可以自动成为 CareKit 中某项任务的完成结果,极大减少了手动录入的负担。
CareKit 的同步机制
新架构支持通过 OCKRemoteStore 实现云端同步。虽然 Apple 没有提供现成的云存储后端,但定义了清晰的同步协议。开发者可以选择自己的后端(CloudKit、Firebase 或自建服务器),只要遵循 OCKStoreSynchronizable 协议即可。这种”提供同步接口但不绑定云服务”的做法很聪明,给了开发者最大的自由度。
代码片段
import CareKit
// 创建 OCKStore 并配置任务
let store = OCKStore(name: "MyCareStore")
// 定义一个每日服药任务
let medicationSchedule = OCKSchedule.dailyAtTime(
hours: 8, minutes: 0,
start: Date(), end: nil,
text: "早餐后服用",
duration: .hours(2),
repeatResults: true
)
var medicationTask = OCKTask(
id: "medication_morning",
title: "服用降压药",
carePlanUUID: nil,
schedule: medicationSchedule
)
medicationTask.instructions = "请随餐服用,每次一片"
medicationTask.impactsAdherence = true
// 保存任务到 store
store.addTask(medicationTask) { result in
switch result {
case .success(let task):
print("任务创建成功: \(task.id)")
case .failure(let error):
print("创建失败: \(error)")
}
}
// 查询某任务今日的完成情况
let query = OCKOutcomeQuery()
query.taskIDs = ["medication_morning"]
query.dateInterval = DateInterval(start: Date().startOfDay, end: Date().endOfDay)
store.fetchOutcomeQuery(query) { result in
switch result {
case .success(let outcomes):
if outcomes.isEmpty {
print("今日尚未服药")
} else {
print("今日已服药,记录数: \(outcomes.count)")
// 查看具体的服药时间
for outcome in outcomes {
for value in outcome.values {
print("服药时间: \(value.date ?? outcome.date)")
}
}
}
case .failure(let error):
print("查询失败: \(error)")
}
}
// 记录任务完成(用户标记已服药)
func markMedicationTaken(for taskID: String) {
let scheduleEvent = OCKScheduleEvent(
start: Date(),
end: Date().addingTimeInterval(3600),
element: 0,
occurrence: 0
)
var outcome = OCKOutcome(
taskUUID: UUID(), // 对应任务的 UUID
taskOccurrenceIndex: 0,
values: [
OCKOutcomeValue(
boolean: true,
kind: "medicationTaken"
)
]
)
store.addOutcome(outcome) { result in
switch result {
case .success:
print("服药记录已保存")
case .failure(let error):
print("保存失败: \(error)")
}
}
}
最佳实践
- 在应用启动时就初始化
OCKStore,避免在 View 层重复创建实例导致数据不一致 - 使用
OCKSchedule的 builder API 构建复杂的时间表,不要手动拼接日期数组 - 为每种健康任务定义清晰的
id命名规范,方便后续查询和统计 - 测试时使用内存 store(
OCKStore(name: "Test", type: .inMemory)),避免污染真实数据 - 考虑与 HealthKit 的集成时,先梳理清楚哪些数据应该由用户主动记录、哪些可以自动采集
还有什么值得关注
- CareKit 现在是完全开源的,你可以在 GitHub 上查看源码并提交 issue
- 框架内置了自适应提醒功能,可以根据用户的完成率自动调整提醒频率
- Session 展示了一个配合 SwiftUI 使用的完整示例,新的 Card View 组件可以直接展示任务进度