大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 WorkoutKit 构建自定义训练
WorkoutKit 让你可以轻松地为 Apple Watch 上的体能训练 App 创建、预览和安排计划训练。了解如何构建自定义间隔时间、创建提醒以及使用内置预览 UI,将你自己的常规训练计划发送到 Apple Watch。
资源
相关视频
WWDC23
-
下载
♪ ♪
Tu:大家好 我是 Tu Nguyen 是 Workout 团队的一名工程师 今天 我将和我的同事 Abhiraj 一起为大家介绍 如何为 Apple Watch 构建自定义训练计划 在 watchOS 9 中 我们为 体能训练 App 引入了新的训练类型 让用户可以创建和自定义 他们理想的训练体验: 第一 基于目标进行训练 其中 用户可以根据单一目标 如距离、能量或时间等进行训练 第二 Pacer 训练 它会将重点放在配速或速度方面 第三 Swim-bike-run 训练 适合铁人三项运动员计划游泳、 自行车和跑步之间的无缝衔接训练 第四 自定义训练 结合了结构化步骤 与自定义目标和提醒 在 iOS 17 和 watchOS 10 中 我们将所有这些训练类型 加入到一个名为 WorkoutKit 的新框架中
WorkoutKit 是一个全新的 Swift 框架 该框架让你可以 在自己的 App 中创建和自定义 用户能在体能训练 App 中 创建的所有不同训练类型 它同时也起到桥梁作用 帮助你将这些训练加入到 体能训练 App 中 供用户执行 WorkoutKit 提供预览 UI 以及对已计划训练的同步功能 我们将这四种训练类型 加入到了 WorkoutKit 今天我们将重点讲解自定义训练 在本课程中 我们将介绍如何构建自定义训练、 预览导出 以及如何计划训练 先来介绍如何构建自定义训练 自定义训练是用户以结构化方式 集中训练的好方法 其中包含一系列不同的步骤 用于引导用户完成训练 在查看自定义训练时 有三个不同的阶段 首先 我们在训练开始时会有一个步骤 那就是热身 接着 我们有一个 可重复分块的有序集合 每个分块中包含各自的步骤组合 这些可重复分块 代表了大部分的训练内容 最后 训练结束时会有一个 缓和步骤 现在 无论是热身、缓和 还是可重复分块中的步骤 每个步骤都包含两个重要属性 首先 每个步骤都包含一个单一目标 目标定义了自定义训练中的步骤进度 当一个目标完成时 自定义训练会进入下一个步骤
自定义训练中的步骤 可以设置时间或距离目标(如适用) 你还可以设置开放式目标 这需要用户手动逐步执行步骤
其次 每个步骤都可包含一个提醒 提醒将告知用户某特定指标的信息 说明用户当前的表现 例如 用户可能希望 在心率超过某个阈值时 收到提醒
我们提供了配速、步频、 功率和心率提醒支持
现在我们了解了步骤的组成 接下来 更详细地介绍一下分块
分块中包含的步骤 分为运动步骤或恢复步骤 分块中的步骤 包含各自的目标和提醒 就像之前看到的 在你的分块中 可拥有 任意数量的步骤并按任意顺序排序 分块也是可重复的 可以指定所需分块的重复循环次数 现在来看看 这如何转化为 Apple Watch 上的 内置训练体验 首先 我们看到用户当前的步骤 是分块内的运动步骤 该步骤中有一个距离目标 我们看到当前目标进度 还剩 0.2 英里 该步骤中还有当前功率的提醒 会在底部显示 如果你没有为该步骤指定提醒 手表将显示用户当前的心率
最后 我们还提供预览 显示下一步是一个 基于时间目标的恢复步骤 通过步骤和分块 你可以构建完整的自定义训练
同样 在最开始 我们会有一个热身步骤 然后是一系列包含运动步骤 和恢复步骤的可重复分块 训练中的大部分时间 都是在进行这些分块 最后是缓和步骤 现在我将交给我的同事 Abhiraj 由他为各位展示如何使用 WorkoutKit 构建自定义训练 Abhiraj:大家好 我是 Abhiraj 是 Workout 团队的一名工程师 正如 Tu 所提到的 使用 WorkoutKit 你可以创建 目标、Pacer、Swim-bike-run 和自定义训练这四种训练类型 让我们以自定义室外骑行训练为例 对于此训练 我们将有四个步骤: 热身、两个包含运动步骤 和恢复步骤的可重复分块 以及最后的缓和步骤 对于热身步骤 我们将使用开放式目标 我们的第一个分块 包含一个带有距离目标 和配速提醒的运动步骤 以及一个带有距离目标 和心率提醒的恢复步骤 这个分块将会有四次循环 第二个分块包含一个带有 时间目标和功率提醒的运动步骤 以及一个带有时间目标 和心率提醒的恢复步骤 最后 我们的缓和步骤 将有一个基于时间的目标 一起来看看如何在代码中表示 先从热身步骤开始 首先 我们导入 WorkoutKit 如前所述 我们的热身步骤 有一个不带提醒的开放式目标 在这种情况下 我们将用默认初始化定式来创建它 接下来创建该训练的第一个分块 在第一个分块中 有两个步骤 第一个步骤是带有距离目标 和配速提醒的运动步骤
因为我们使用 HKQuantity 和 HKUnit 来表示目标和提醒 所以在此需要导入 HealthKit 现在 我们将使用 WorkoutGoal 来设置一个 2 英里的目标 我们还将为该步骤添加一个配速提醒 目标配速为每小时 10 英里 首先 创建一个配速值为 10 英里/小时的 HKQuantity 我们将使用 WorkoutAlert 来创建这个提醒 要创建 WorkoutAlert 就需要 WorkoutAlertTargetType 在本例中 目标配速为 10 英里/小时 还需要一个 WorkoutAlertType 本例中的提醒类型是当前配速 现在 我们可以 创建配速 WorkoutAlert 现在 为创建我们的运动步骤 我们将使用类型为 work 的 BlockStep 目标和提醒参数值为 twoMileGoal 和 paceAlert
该分块中的第二个步骤是恢复步骤 我们将创建一个长达半英里的恢复目标 以及一个心率区间为 1 的提醒
然后 我们可以使用类型为 rest 的 BlockStep 来创建恢复步骤 现在 我们可以使用刚才定义的 运动步骤和恢复步骤来创建分块 使用 IntervalBlock 即可创建 参数 包括一个步骤数组及循环次数为 4
这样 我们的第一个分块就完成了 接下来 继续创建第二个分块 在这个分块中 也有两个步骤 第一个步骤是带有时间目标 和功率提醒的运动步骤 我们设置了一个两分钟的目标 对于该运动分块 我们创建一个 250-275 瓦的 功率范围提醒 我们创建类型为 range 的 WorkoutTargetType 并创建 WorkoutAlert 最后 使用刚才创建的 目标和提醒来创建 BlockStep
该分块中的第二步是个恢复步骤 我们创建一个 30 秒的目标 以及心率区间为 1 的提醒 然后就可以创建恢复步骤
现在可使用刚才定义的运动 和恢复步骤来创建第二个分块 循环次数设置为 2
最后 我们来设置缓和步骤 我们希望缓和步骤 有一个基于时间的目标 让我们在此创建该步骤
我们创建了类型为 time 的 WorkoutGoal 并用来创建 CooldownStep 目标设置为 fiveMinuteGoal 现在我们来整体组合一下
使用我们目前构建的所有内容 包括热身步骤、分块 1、分块 2 和缓和步骤 我们可以创建 这个自定义训练组合 将任务类型设置为 cycling 位置则设置为 outdoor CustomWorkoutComposition 初始化定式的 LocationType 参数 是可选的 默认设置为 outdoor 现在将所有内容组合起来 创建 名为“我的体能训练”的自定义训练
你可能还想知道为什么 CustomWorkoutComposition 的 初始化定式前面有一个 try 这是因为我们正在验证组合 现在来介绍一下验证训练组合的重要性 验证可确保一个连贯的训练结构 并防止在训练运行期间出现任何问题 例如 距离目标不应用于 非基于距离的训练组合 同样 配速提醒不应用于 不支持配速的训练 例如:椭圆机 为帮助解决这些问题 我们有一系列的验证 当用户设置某些属性时 例如:设置训练任务类型 或通过某些 API 运行接入时 就会进行验证
我们还创建了 WorkoutComposition 包装器 用于执行其他操作 例如 我们还创建了 API 来将训练组合导入/导出到文件中 这些文件可以在设备之间共享 使用 dataRepresentation 可导出为 JSON 或二进制文件 我们建议将训练组合 导出为二进制格式 因为这种格式的文件要小得多 现在 我将画面交回给 Tu 让他为各位介绍如何预览组合 Tu:谢谢你 Abhiraj 很高兴看到 我们能如何利用这些 API 来构建完全自定义的训练 现在 来看看我们有了 训练组合之后可以做些什么 在 WorkoutKit 中 有几项工作可使用训练组合 首先 正如 Abhiraj 之前提到的 可以将组合导出到一个 扩展名为 .workout 的文件中 以便共享和分发 请注意 在调用某些 API 时 系统会自动进行验证 导出一个组合正是这样一个例子
我们还有 API 可以让你向用户呈现 训练组合的内容预览 这在 iOS 和 watchOS 上 有不同的表现形式
在 iOS 上 当你在组合上 调用预览 API 时 将在你的 App 顶部 呈现一个独立执行的 UI 并显示你的训练组合的全部内容 在本例中 我们有一个自定义的训练组合 标题在顶部突出显示 还有步骤及分块列表 包括目标和提醒 还有一个选项 允许用户直接将训练计划 保存到他们的 Apple Watch 上的体能训练 App 中 现在 如果我们回到 watchOS 调用预览 API 将会启动体能训练 App 并显示训练组合的内容 从这里 用户可以立即开始训练 或将其保存 以备后用
我将再次把画面交给 Abhiraj 让他为你 展示 WorkoutKit 的这些预览选项 Abhiraj:现在我们有了一个很棒的 训练计划 可供用户保存 正如刚才介绍的 我们可以使用 WorkoutComposition 来对训练进行其他操作 例如验证 通过 WorkoutComposition 我们就可以向用户呈现预览 预览 API 针对 iOS 和 watchOS 进行了优化 可为用户提供预览、保存 或开始训练的便捷方式 现在让我们将之前创建的骑行训练 封装在 WorkoutComposition 中
你可以使用 Tu 之前提到的任何训练类型 与 WorkoutComposition 一起使用 现在使用 WorkoutComposition 上的 presentPreview 函数 来呈现预览
我们在这里使用任务分块 因为此 API 专门用于和 Swift 的 modern concurrency 功能 搭配使用 如前所述 presentPreview 将根据当前运行的平台 显示不同的训练预览 来了解一下它的工作原理 在 iOS 上 该函数 会在 App 上方呈现远程视图 视图中会显示训练 和一个选项 方便用户直接将其 保存到 Apple Watch 上的 体能训练 App 中 “添加到手表”按钮 可将新的训练更新到体能训练 App 预览功能在 Apple Watch 上 有不同的表现形式 调用 watchOS 上的预览功能 不会在 App 上方呈现表格 而是会启动体能训练 App 并显示训练预览 现在我将画面交回给 Tu 由他来为你介绍如何安排训练 Tu:谢谢你 Abhiraj 这些预览选项真的很有帮助 用户可轻松获得单个训练组合 并与之进行快速交互 但如果你有一系列训练 需要用户在一段时间内完成 该怎么办? 例如:假设你今天 为用户计划了骑行训练 然后本周晚些时候进行徒步远足 之后几天是打高尔夫球 可能还会安排休息 然后再开始骑行训练 你可以使用组合和预览 API 将训练计划直接保存到 体能训练 App 中 但现在用户需要 负责管理所有这些训练 并记住何时需要完成它们 可扩展性不强 为了简化整个过程 作为 WorkoutKit 的一部分 你的 App 可直接 在体能训练 App 中计划训练 让我们看看过程是怎么样的 在计划训练时 你的 App 将在体能训练 App 的 顶部拥有一个专用空间 该空间将显示 你的 App 图标和名称 并提供当天的下一个训练预览 轻点这里将立即开始 所显示的已计划训练
轻点“...”将显示更多详细信息 包括已同步的 即将开始的计划训练
计划训练需要用户许可 而同步会在本地处理 用户能够查看接下来七天 和前七天的训练计划 你一次最多可同步 15 个训练计划 你可从你的 App 中 查询用户完成的已计划训练
在查询已计划训练时 查询结果只包含你创建的组合、 计划日期以及用户是否已完成训练 而不包含任何健康数据 因此 如果你想从已完成的训练中 获取实际的健康统计数据 请参考 HealthKit API 作为 WorkoutKit 的一部分 我们提供了一个 HKWorkout 的 扩展插件来检索训练组合 (如果适用) 现在我将画面交回给 Abhiraj 由他来为你展示如何使用 WorkoutKit 来计划训练 Abhiraj:谢谢你 Tu 针对为用户计划训练的 App 我们提供了一组 API 来支持将训练组合 同步到 Apple Watch 中 以便在体能训练 App 中使用 现在就来实际构建一个 利用 WorkoutKit API 的 App 我们需要将计划日期 与训练组合相关联 然后进行同步 让我来为你展示该如何操作 我已经开始构建一个 App 它使用占位符 与 WorkoutKit API 进行交互 来看看如何利用 WorkoutKit 使其功能正常 在开始将训练计划 同步到体能训练 App 之前 我们需要获得用户许可 你可在 WorkoutPlan 上 调用 authorizationState 来检查 App 当前的权限 由于我们尚未申请权限 因此 我们在 WorkoutPlan 上 调用 requestAuthorization 来请求授权
我将点击“请求授权”按钮
在调用 requestAuthorization() 时 用户会收到提醒 告知其选择加入同步 用户也可在 iOS 上的 Watch App 和 watchOS 上的 Setting App 中 修改“体能训练”设置中的这一设置
现在我们已经授权 App 可从 Apple Watch 上的 体能训练 App 获取当前的训练计划 你可使用 WorkoutPlan.current 来查询 WorkoutPlan
WorkoutPlan 是一个接口 用来存储和修改 来自 App 的已计划训练 我将轻点“获取训练计划”按钮
因为我们尚未计划任何训练 因此计划中没有已计划的训练
接着 让我们创建并计划一些训练 我今天想去打高尔夫球 且本周晚些时候进行骑行训练 让我们使用一些 新的训练组合来创建这个计划
ScheduledWorkoutComposition 对象包含一个训练组合、 计划日期以及一个完成状态 我已将高尔夫的 scheduledDate 设为今天 骑行训练的 scheduledDate 则是明天
来看看在 App 中是什么样子 你可以看到 我今天安排了高尔夫训练 几天后还有骑行训练 现在我们已经创建了计划 接下来将其同步到体能训练 App 中 使用当前的训练计划 我们可将这些新的已计划训练 添加到 scheduledCompositions 数组中 最后 为将这些训练 添加到体能训练 App 中 我们要调用 workoutPlan.save()
来看看实际操作是如何呈现的吧
太棒了 现在这些训练都已经被同步了 正如 Tu 所提到的 在计划一个训练时 你的 App 将在 体能训练 App 的顶部拥有专用空间 让我们细致了解一下它的外观 现在打开体能训练 App
可以看到 我的 App 图标和名称都有显示 因为我今天安排了高尔夫训练 轻点这里将开始训练 可以点击“...” 查看我即将到来的日程计划 在第一个屏幕上 可以 看到我今天计划的所有训练 如果轻点“查看更多” 将能够看到接下来的七天 和前七天所计划的训练 这里 我看到了今天的高尔夫训练 和之前已同步的即将到来的骑行训练
现在你已了解如何呈现已计划的训练 以及你的 App 如何 在体能训练 App 中拥有专用空间 如你所知 我今天计划打一轮高尔夫 我的开球时间快到了
如果你不介意 我很快就回来
我回来了 我打了一轮很棒的高尔夫球 后九洞打了 72 杆 用户在体能训练 App 中 完成已计划的训练后 完成状态将会更新 你可使用 WorkoutPlan.current 查询 WorkoutPlan 从而确定哪些训练已完成 如果在你的 App 中 标记了训练为“已完成” 你应更新完成状态 让用户在任何地方 都能拥有最新的信息 现在回到我们的代码
在示例 App 中 可以检查 scheduledComposition 是否已完成 如果已完成 我们要将其标记为“已完成” 一起来看看实际如何操作
将你的 App 与体能训练 App 保持同步是一个很好的做法 现在你已基本了解如何在 App 中实现体能训练计划 API 内容涵盖请求授权和将组合 同步到体能训练 App 等 现在 我将画面交回给 Tu Tu:谢谢你 Abhiraj 很高兴看到你的高尔夫球技有所提高 接下来总结一些最佳实践 有助于在你的 App 中 采用 WorkoutKit
应考虑哪种组合类型 最适合你想给用户显示的 训练体验 我们看到自定义训练 是一种非常实用的组合类型 特别是当一项训练 需要不同程度的努力和关注 且有自定义的目标和提醒时 尤为有帮助 不过 游泳不支持自定义训练 而是要使用目标组合 此外 提醒仅适用于自定义训练 如果你不需要为 30 分钟的跑步 这样简单的事情 指定自己的提醒 请考虑使用目标或 Pacer 组合 务必完成训练组合的验证 我们提供非常细化的验证错误 以便帮助你确定任何不相符项 或错误的来源 提醒一下 并非所有的 任务类型都支持距离目标 可考虑使用时间或开放式目标 也并非所有任务类型 都支持自定义训练中的某些提醒 可考虑使用替代方案 例如:心率区间提醒
保持你的已计划训练不断更新 充分利用你的 App 可拥有的 任何前台或后台运行时间 来更新你的训练计划 最后 请向我们提供你的反馈意见 试试使用 API 吧 你今天看到的所有示例代码都可 在 developer.apple.com/cn/ 上找到 还有 记得观看有关同步训练课程中的 HealthKit 一讲 感谢你的观看 ♪ ♪
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。