WWDC Quick Look 💓 By SwiftGGTeam
What’s new in watchOS 11

What’s new in watchOS 11

观看原视频

Highlight

watchOS 11 让 iOS Live Activity 自动同步到手表 Smart Stack,并提供 RelevantContext API 让 Widget 按时间和场景自动浮现,加上 Interactive Widgets 和 AccessoryWidgetGroup 模板,用户转一下表冠就能完成操作而不用打开 App。


核心内容

手表上最稀缺的资源是用户注意力。过去开发者要在 Apple Watch 上获得曝光,只有两条路:让用户主动打开 App,或者挤进 Complication 里那一小块位置。但 Complication 空间有限,用户也不会频繁打开手表 App——打开率低、停留时间短,很多团队投入大量精力做 watchOS 版本,实际使用数据却很难看。

watchOS 11 给出了一套新解法:把信息前移到 Smart Stack。转一下表冠就能看到航班状态、回复消息、控制智能家居,你的 App 在这个场景里露脸的频率远高于等用户打开 App。具体来说有三个核心变化。

第一,iOS Live Activity 自动同步到手表。你不需要写任何手表端代码,iPhone 上的 Live Activity 会直接出现在 Smart Stack 里。如果你愿意提供 .small family 的自定义视图,系统会优先使用你的定制内容而非 Dynamic Island 的默认视图。第二,RelevantContext API 让 Widget 按时间、地点、睡眠、运动等场景自动浮现,开发者只需在 TimelineProvider 里声明”什么时候我的 Widget 最有用”,系统负责调度。第三,Interactive Widgets 来到 watchOS——按钮和开关直接在 Widget 上生效,用户不用跳转 App 就能锁门、暂停播放、标记完成。

这三件事叠加在一起,策略方向很明确:与其优化手表 App 的打开率,不如把关键信息和操作前移到 Smart Stack。

详细内容

Live Activity 同步到手表(01:06

iOS App 的 Live Activity 在 watchOS 11 会自动出现在 Smart Stack 中,零代码改动。系统默认使用 Dynamic Island 的 leading 和 trailing 视图。如果你想提供更好的手表体验,可以在 ActivityConfiguration 上添加 .supplementalActivityFamilies 修饰符,指定 .small family 提供自定义视图:

ActivityConfiguration(for: MyLiveActivityAttributes.self) { context in
    MyLiveActivityView(context: context)
} dynamicIsland: { context in
    DynamicIsland {
        // ...
    }
}
.supplementalActivityFamilies([.small])

关键点:

  • .supplementalActivityFamilies([.small]) 告诉系统你的 Live Activity 支持 Smart Stack 的 compact 布局
  • 添加后系统优先使用你的自定义视图,而非 Dynamic Island 视图
  • 可以通过 Environment 区分 .small(手表 Smart Stack)和 .medium(iPhone 锁屏)分别定制布局
  • 即使没有 watchOS App,Live Activity 也会自动同步到手表

RelevantContext API(03:00

TimelineProvider 中实现 relevances() 方法,声明 Widget 在什么场景下最有用:

func relevances() -> WidgetRelevances<Void> {
    let dueDate = Calendar.current.date(byAdding: .hour, value: 1, to: Date())!
    let context = RelevantContext.date(dueDate...dueDate)
    return WidgetRelevances([WidgetRelevanceEntry(relevance: context)])
}

关键点:

  • RelevantContext 支持多种上下文:.date(时间)、.location(位置)、.sleep(睡眠时段)、.fitness(运动状态,含 .activityRingsIncomplete 条件)
  • 对于使用 AppIntentConfiguration 的 Widget,可以按 intent 分别提供相关性——比如咖啡店 Widget 为每个收藏门店提供各自的位置上下文
  • WidgetRelevanceEntry 的初始化器接受 configuration 参数,关联到具体的 AppIntent
  • 用户更改偏好后调用 invalidateRelevances() 让系统重新请求
  • 系统同时考虑多个 Widget 的相关性建议,你的 Widget 不保证一定会出现

Interactive Widgets(05:47

在 watchOS Widget 中添加交互跟 iOS 17 一样的模式——在视图中放 ButtonToggle,对应 Intent 实现 perform() 方法:

// Widget 视图中
Button(intent: LockDoorIntent()) {
    Image(systemName: "lock")
}

// AppIntent 中
struct LockDoorIntent: AppIntent {
    static var title: LocalizedStringResource = "Lock Door"

    func perform() async throws -> some IntentResult {
        // 执行锁门操作
        return .result()
    }
}

关键点:

  • 所有 watchOS Widget family 都支持交互
  • 多个交互目标可以放在同一个 Widget 内,但受限于 Widget 形状和大小
  • 对于可能误触的操作,使用 requestConfirmation(.lowConfidenceSource) 让系统在检测到低置信度来源时弹出确认提示
  • .lowConfidenceSource 让系统自行判断何时需要确认,比如用户在公司时远程开家门

AccessoryWidgetGroup 模板(07:54

这是 watchOS 11 新增的视图模板,用于 accessoryRectangular Widget,最多展示三个内容项:

AccessoryWidgetGroup {
    Label("Messages", systemImage: "message")
} content: {
    ContactView(name: "Alice")
    ContactView(name: "Bob")
    ContactView(name: "Charlie")
}
.accessoryWidgetGroupStyle(.circular)

关键点:

  • LabelContent 两部分组成:Label 默认显示 Widget Extension 的 bundle name,建议自定义
  • Content 最多展示 3 个视图,超过则只显示前 3 个
  • 每个 Content 视图可以是交互式的(Button),也可以用 Link 跳转到 App 的不同页面
  • 如果不足 3 个视图,系统自动插入空白占位(点击打开 App,颜色不可配置)
  • .accessoryWidgetGroupStyle(.circular).roundedSquare 控制遮罩形状,默认 .circular
  • 字体、视图大小、边距都已预配置,开发者只关注内容

Double Tap 扩展(10:33

watchOS 11 中 Double Tap 手势在 App 内自动支持 ListScrollView 和 vertical TabView 的滚动。你还可以用 .handGestureShortcut(.primaryAction) 指定主操作:

Button("Complete") {
    completeTask()
}
.handGestureShortcut(.primaryAction)

关键点:

  • 双击时系统自动高亮 Button 或 Toggle 的轮廓,提供视觉反馈
  • 高亮形状可以用 clipShape 自定义
  • 同一时刻只有一个元素可以成为 primaryAction
  • 控件在屏幕上时触发操作,不在屏幕上时先滚动到控件位置
  • 如果 App 已经通过 List/ScrollView 继承了自动滚动行为,不要再给这些视图内的控件加 .primaryAction,避免行为冲突

WorkoutKit 和 HealthKit 更新(12:28

WorkoutKit 新增泳池游泳活动类型,加入 Custom Workouts API(之前只有骑行和跑步)。新的 distanceWithTime 目标类型允许一个训练步骤同时设定距离和时间目标。所有自定义训练类型的 Warmup、Work、Recovery、Cooldown 步骤现在支持 displayName 属性自定义名称。

HealthKit 新增 State of Mind API,可以读写情绪和情感数据。

核心启发

  1. 为 Live Activity 提供 .small 视图:如果你的 iOS App 已经有 Live Activity,watchOS 11 自动同步是零成本曝光。但 Dynamic Island 视图在手表上信息密度不够——花半天为 .small family 写一个精简版视图,信息量提升明显。怎么开始:在现有 ActivityConfiguration 上加 .supplementalActivityFamilies([.small]),用 Environment 区分布局。

  2. 用 RelevantContext 让 Widget 在对的时间浮现:通勤、外卖、运动、待办——这些场景天然有时间或地点关联。RelevantContext 的投入产出比极高,几行代码就能让系统在用户最需要你的信息时把 Widget 推到 Smart Stack 顶部。怎么开始:在 TimelineProvider 里实现 relevances() 方法,从 .date.location 上下文开始。

  3. 用 AccessoryWidgetGroup 快速搭建交互式 Widget:这个模板预配置了字体、大小和边距,最多放三个交互目标,省掉大量布局调试时间。Messages Widget 展示三个置顶联系人就是典型案例。怎么开始:用 AccessoryWidgetGroup 替换现有的 accessoryRectangular 布局,选择 .circular.roundedSquare 风格。

  4. 给关键操作加 .handGestureShortcut(.primaryAction):用户手腕不方便触屏时(提着东西、跑步中),Double Tap 是最高效的交互方式。在 App 的主操作按钮上加一个修饰符就能支持,系统自动处理视觉反馈。怎么开始:找到 App 中最常用的 Button 或 Toggle,加上 .handGestureShortcut(.primaryAction)

关联 Session

评论

GitHub Issues · utterances