WWDC Quick Look 💓 By SwiftGGTeam
Widgets Code-along, part 1: The adventure begins

Widgets Code-along, part 1: The adventure begins

观看原视频

Highlight

本场 code-along 用 Emoji Rangers 示例 App 复用 AvatarView 创建 Widget Extension,并把角色数据接入 TimelineProvider,随后通过 supportedFamilies 限制尺寸、用 placeholder 预览等待 timeline 时的显示状态。

核心内容

Emoji Rangers 是一个跟踪角色状态的游戏。Power Panda 正在恢复,Spouty 和 Egghead 也有各自的状态。主 App 里已经有一个左上角的状态方块,刚好适合放到主屏幕上,让玩家不用打开 App 就知道角色什么时候能继续行动。

Apple 在这场 code-along 里没有先讲完整架构图,而是直接从这个方块开始。Widget 的核心被压缩成一句话:它是一个会随时间更新的 SwiftUI view。已有的 AvatarView 可以继续用,开发者要做的是把它放进 Widget Extension,并让 WidgetKit 在 Gallery、主屏幕和等待 timeline 时拿到正确的内容。

第一集的目标很小:先让一个 small widget 跑起来。流程从 Xcode 新建 widget target 开始,接着把 AvatarView 加进 target,用 WidgetPreviewContext 预览真实尺寸,再通过 entry、snapshot、timeline 和 placeholder 把同一份角色状态接到 WidgetKit 生命周期里。

这也是本 session 的价值。它把 “做 widget” 拆成几个可以马上验证的小步骤:先复用一个 SwiftUI view,再补显示名称和描述,再把数据放进 entry,最后只开放当前能做好的一种尺寸。

详细内容

00:48)Widget 在这里被定义成一个 SwiftUI view,并且会随时间更新。演示从现有的 AvatarView 入手,因为这个视图已经能表达角色头像和状态。

由于本 session 没有官方 code snippets,下面的代码块只保留 transcript 明确出现的调用点;完整工程以资源里的 Building Widgets Using WidgetKit and SwiftUI 下载项目为准。

AvatarView(character: panda)

关键点:

  • AvatarView 是主 App 中已经存在的 SwiftUI view。
  • character 对应演示里的 Power Panda 这类 Emoji Rangers 角色数据。
  • 第一步先复用已有视图,避免在 widget target 里重新设计一套 UI。

02:39)把视图变成 widget 的第一步是在 Xcode 里新建 Widget Extension target。新 target 激活后,把需要的视图文件加入 target,然后在 SwiftUI Preview 中用 widget 尺寸检查效果。

AvatarView(character: panda)
    .previewContext(WidgetPreviewContext(family: .systemSmall))

关键点:

  • WidgetPreviewContext 让 SwiftUI Preview 按 widget 环境渲染。
  • family 对应 Add sheet 里看到的 small、medium、large 尺寸。
  • 演示选择先验证状态方块适合 small widget 的显示空间。

04:23)Widget 模板里需要补 DisplayNameDescription,随后进入主 EntryViewEmojiRangerWidgetEntryView 已经带有 entry,角色数据可以放到 entry 里,再传给 AvatarView

EmojiRangerWidgetEntryView(entry: entry)

AvatarView(character: entry.character)

关键点:

  • DisplayNameDescription 决定用户在 Widget Gallery 中看到的名称和说明。
  • entry 是 widget view 读取数据的入口。
  • AvatarView 不直接去主 App 查数据,而是从 entry 接收角色对象。

05:17)Entry 来自 timeline provider。Session 把 provider 讲成 widget 的核心引擎:WidgetKit 需要单条内容时取 snapshot;用户已经把 widget 加到设备后,系统取完整 timeline。

TimelineProvider
  .getSnapshot -> one entry for Widget Gallery
  .getTimeline -> entries for the added widget

关键点:

  • getSnapshot 服务 Widget Gallery 这类只需要一条内容的场景。
  • getTimeline 服务已经添加到主屏幕或 Today View 的 widget。
  • 第一集暂时只放一条 entry,先跑通显示链路,再进入后续 timeline 设计。

06:22)首次运行后,Add sheet 同时显示 small、medium、large。演示者认为此时还没准备好支持所有尺寸,所以只开放当前能做好的一种尺寸。

EmojiRangerWidget()
    .supportedFamilies([.systemSmall])

关键点:

  • supportedFamilies 是 widget configuration 上的额外 modifier。
  • 限制尺寸能让首版 widget 避免在 medium、large 中浪费空间。
  • 最终检查时,Widget Gallery 只显示一个支持尺寸,并能直接添加到 Home Screen。

06:55)模板里还有 PlaceholderView。它在 WidgetKit 等待 timeline 时出现。演示把 placeholder 也改成 AvatarView,再用 isPlaceholder 让文本和图片自动变成灰色圆角占位。

AvatarView(character: panda)
    .isPlaceholder(true)

关键点:

  • placeholder 不需要真实 entry,演示中继续传入 Panda。
  • isPlaceholder 会把文本替换成灰色圆角矩形,图片也会自动替换。
  • SwiftUI Preview 可以同时放真实 widget 和 placeholder,方便比较等待状态和完成状态。

核心启发

1. 给角色状态做 small widget

做什么:把游戏、健身或学习 App 里的单个状态块放到主屏幕。

为什么值得做:session 选择 Emoji Rangers 的状态方块,是因为它已经是一个可一眼读懂的 SwiftUI view。

怎么开始:先找出 App 中一个类似 AvatarView 的小视图,把它加入 Widget Extension target,再用 WidgetPreviewContext 检查 small 尺寸。

做什么:让 Gallery 里的预览显示一个代表性角色或任务,而不是空状态。

为什么值得做:transcript 明确说 snapshot 是 WidgetKit 只需要一条 entry 时使用的内容,例如 Widget Gallery。

怎么开始:在 provider 的 snapshot 路径里放一个最近或最有代表性的对象,先验证它能完整传到 EntryView

3. 用 placeholder 预览等待状态

做什么:为 widget 等待 timeline 的阶段做一个可读的 loading 外观。

为什么值得做:session 演示了 isPlaceholder 会自动把文本和图片替换成系统占位效果。

怎么开始:把真实 widget view 和 placeholder view 放进同一个 preview group,给 placeholder 版本加 isPlaceholder

4. 首版只开放一个尺寸

做什么:先发布 small widget,等 medium 和 large 有明确内容层级后再扩展。

为什么值得做:演示里 small、medium、large 默认都出现,但当前角色状态方块在其他尺寸里空间利用不好。

怎么开始:在 widget configuration 上加 supportedFamilies,只保留已经验证过的 family。

关联 Session

评论

GitHub Issues · utterances