WWDC Quick Look 💓 By SwiftGGTeam
Widgets Code-along, part 3: Advancing timelines

Widgets Code-along, part 3: Advancing timelines

观看原视频

Highlight

Widget code-along 第三集演示了在 widget extension 内处理 URLSession、用 SwiftUI Link 跳转到 App 内容、用 WidgetBundle 暴露多个 widget,并通过 Intent Extension 为配置提供动态选项。

核心内容

第三集从一个已经有基础 timeline 的项目继续。新的 Leaderboard widget 会把角色按 health 排序展示。问题随之出现:widget 需要取数据,需要让每一行跳到 App 内的角色详情,还要和原来的 Ranger Detail widget 一起出现在 widget gallery。

这几个需求都卡在 widget extension 的边界上。网络请求不能假设由宿主 App 接管;可点击区域要落在 widget 的 SwiftUI 视图里;同一个 extension 里还只能有一个 @main。如果直接把 App 里的写法搬进来,开发者会很快碰到这些边界。

Apple 在这场 code-along 里把边界逐个拆开:timeline provider 用 completion handler 支持异步请求;widget 自己响应它创建的 URLSession,包括 background session;SwiftUI Link 可以把一行 widget 内容变成深链接入口;WidgetBundle 负责把多个 widget 放进同一个 extension;Intent Extension 则把原来写死的配置列表换成动态选项。

最后的结果是一个更接近真实 App 的 widget。它能取数据,能跳转到指定内容,能在一个 extension 里提供多个入口,还能让配置列表跟随远端数据变化。

详细内容

1. 在 widget extension 里取数据

01:28)Leaderboard widget 的数据来自 CharacterDetail 上的 loadLeaderboardData 异步请求。Transcript 明确说明,timeline provider API 使用 completion handler,目的就是让 network fetch 这类异步任务容易接入。

本 session 没有公开 Code tab snippet。下面只保留 transcript 中出现的调用形态,不补全业务实现。

CharacterDetail.loadLeaderboardData
URLSession
data task

关键点:

  • loadLeaderboardData 是 Leaderboard 数据的异步入口。
  • timeline provider 依靠 completion handler 等待异步任务完成。
  • session 中演示的是普通 in-process URL session。
  • 这个请求用本地文件模拟远端 fetch;实际项目里通常会调用 remote Web service。

02:20)background session 在 widget 里有一个特殊点:它完成时不会启动 extension 的 hosting app。Widget 会响应自己创建的所有 URLSession,包括 background session。

onBackgroundURLSessionEvents
sessionIdentifier
completion block

关键点:

  • onBackgroundURLSessionEvents 是 widget configuration 上的 modifier。
  • 它对应 App 里常见的 application delegate 回调职责。
  • 系统提供 sessionIdentifier 和 completion block。
  • transcript 只说明管理方式与 App 中相同,没有展开具体队列或持久化策略。

03:20)Leaderboard 里每一行都是 AllCharactersView 里的一个 HStack。目标是点击某个角色时,直接打开该角色的信息页面。

Link(destination: character.url) {
    HStack {
        ...
    }
}

关键点:

  • Link 是 session 中点名的新 SwiftUI API。
  • destination 使用角色自己的 URL。
  • 原来的 HStack 仍然承载这一行的内容。
  • 点击 widget 行时,系统会高亮该行,然后打开对应角色详情。

3. 用 WidgetBundle 暴露多个 widget

04:36)项目里有 Leaderboard widget 和 Ranger Detail widget,但一个 process 里只能有一个 @main。解决办法是把 @main 从单个 widget 移到 bundle 上。

@main -> WidgetBundle
WidgetBundle -> Leaderboard widget
WidgetBundle -> Ranger Detail widget

关键点:

  • WidgetBundle 用来在同一个 extension 里声明多个 widget。
  • @main 放在 bundle 上,而不是分别放在两个 widget 上。
  • session 中演示的结果是 widget gallery 同时出现 Leaderboard widget 和 Ranger Detail widget。
  • 这个结构适合一个 App 提供多个信息入口。

4. 用 Intent Extension 提供动态配置选项

05:31)上一集已经有可配置 widget,但选项列表是硬编码的。第三集把 SiriKit intent 的参数类型改成 custom type,再由 Intent Extension 提供动态列表。

IntentHandler
identifier
displayString
CharacterDetail.remoteCharacters
Intent identifier -> characterFromName

关键点:

  • custom intent type 默认带有 identifierdisplayString 两个属性。
  • 这些值来自 IntentHandler
  • 选项提供过程也是异步调用,和 timeline 方法类似。
  • session 中把 CharacterDetail.remoteCharacters 加入选项列表,用来模拟从网络取得更多角色。
  • widget 读取用户选择时,用 intent identifier 找回对应角色。

08:01)配置界面最终出现了原始选项 Power Panda、Egghead、Spouty,也出现了远端选项 Mr. Spook、Cake、Octo。用户选择 Mr. Spook 后,Home Screen 上的 widget 展示这个角色。

核心启发

1. 做一个远端排行榜 widget

  • 做什么:把服务端排行榜放到 Home Screen,按最新分数或状态排序。
  • 为什么值得做:session 明确演示了 Leaderboard widget 通过异步请求获取角色列表。
  • 怎么开始:先把 timeline provider 接到现有 fetch 方法;如果请求可能在后台完成,再在 widget configuration 上接入 onBackgroundURLSessionEvents

2. 做一个可点击的列表 widget

  • 做什么:让 widget 的每一行打开 App 内对应详情页。
  • 为什么值得做:session 演示了把 HStack 包进 SwiftUI Link,并把 destination 指向角色 URL。
  • 怎么开始:为列表里的每个实体准备 URL,在 widget row 外层使用 Link(destination:)

3. 用一个 extension 提供多个 widget

  • 做什么:同时提供总览型 widget 和详情型 widget。
  • 为什么值得做:session 演示了 Leaderboard widget 与 Ranger Detail widget 通过 WidgetBundle 同时进入 widget gallery。
  • 怎么开始:把 @main 移到 WidgetBundle,在 bundle body 里列出多个 widget。

4. 做服务端驱动的 widget 配置

  • 做什么:让用户配置 widget 时看到最新项目、设备、角色或关注对象。
  • 为什么值得做:session 通过 Intent Extension 把硬编码列表扩展为动态选项。
  • 怎么开始:把 intent 参数改成 custom type,在 IntentHandler 中返回带有 identifierdisplayString 的选项,并在 widget 里通过 identifier 找回实体。

关联 Session

评论

GitHub Issues · utterances