Highlight
WidgetKit 在 iOS 14 和 macOS Big Sur 通过 Intent 配置、Siri Suggestions 捐赠和 TimelineEntryRelevance,让同一个 widget 实例显示用户选择的内容,并帮助 Smart Stack 在相关时机把它转到顶部。
核心内容
很多 widget 的第一版都能展示信息,但用户很快会遇到第二个问题:同一个 App 里有多份内容,Home Screen 上只想看其中一份。交易 App 的例子很典型。用户可能有多张卡,Recent Purchases widget 只应该显示其中一张卡的交易,也可能只想看食品或交通这类分类。
如果每个选择都要开发者自己做设置页,widget 会变重。Apple 采用了另一条路径:开发者在 Intent Definition File 里声明参数,系统根据这些参数生成 widget 背面的配置界面。用户长按 widget、点 Edit Widget,就能选择 Card 和 Category。配置后的 intent 实例会在运行时传给 widget extension。(03:24)
配置解决的是“显示哪一份内容”。智能调度解决的是“什么时候显示”。Smart Stack 会根据用户行为和 App 提供的相关性信号,把合适的 widget 转到栈顶。天气 App 里即将到来的雷暴、交易 App 里超过 50 美元的消费,都是 session 里给出的具体场景。(17:43)
这场 session 的关键,是把配置和智能调度连起来。用户在 widget 上选择了某张卡;App 在用户查看同一张卡时捐赠 intent;系统学习这个时间规律;当同一张卡的 widget 已经存在于 Smart Stack 里,系统就有机会在正确时间把它显示出来。(20:04)
详细内容
用 Intent 定义 widget 配置项
(03:24)Widget 的配置界面来自 intent。Intent 包含一组有顺序的参数,每个参数都会变成配置 UI 上的一行。演示里的 ViewRecentPurchasesIntent 有两个参数:Card 和 Category。
Intent Definition File
ViewRecentPurchases intent
parameters:
Card -> custom Card type
Category -> enum, default value: All
eligible:
Intent is eligible for widgets
关键点:
Intent Definition File是 Xcode 里声明 intent、参数和类型的位置。Intent is eligible for widgets让这个 intent 可以作为 widget 配置。Card用自定义类型,因为它代表 App 内部的一张卡。Category用枚举,因为分类集合是固定的。- Xcode 会生成 intent class,例如
ViewRecentPurchasesIntent,里面有对应参数属性。
给配置项提供动态选项
(09:40)很多配置值不能写死在 Intent Definition File 里。信用卡列表会随登录用户变化,所以 Card 参数需要动态选项。打开 Dynamic Options 后,系统会生成 intent handler protocol,要求 App 或 Intents extension 提供候选值。
Card parameter
Dynamic Options: on
generated methods:
provideCardOptionsCollection
defaultCard
runtime data:
app cards -> custom Card objects -> INObjectCollection -> completion handler
关键点:
provideCardOptionsCollection返回用户可选的 Card 列表。defaultCard返回第一次添加 widget 时使用的默认 Card。INObjectCollection可以返回平铺列表,也可以按 section 分组。- 开启搜索后,
provideCardOptionsCollection会收到 search term,用户输入时可以返回额外搜索结果。 - 默认值很重要,因为新 widget 拖到 Home Screen 时会先显示默认 Card 的内容。
从 StaticConfiguration 切到 IntentConfiguration
(13:47)配置项定义好后,widget extension 要从静态配置改成 intent 配置。Provider 也要改成 IntentTimelineProvider,这样 timeline 方法会收到用户选好的 intent 参数。
Widget definition:
StaticConfiguration
-> IntentConfiguration(intent: ViewRecentPurchasesIntent)
Timeline provider:
TimelineProvider
-> IntentTimelineProvider
timeline input:
intent.card
intent.category
关键点:
IntentConfiguration告诉 WidgetKit 这个 widget 用哪一个 intent 做配置。IntentTimelineProvider的方法会多拿到一个 intent 参数。- widget 不再只显示默认卡片,而是根据
intent.card选择交易数据。 intent.category可以继续过滤交易列表。- 同一个 widget 类型可以有多个实例,每个实例保存不同配置。
定制配置页的文字、颜色和参数关系
(15:13)系统生成配置 UI,不代表开发者完全不能调整。Widget extension 可以设置配置页标题和描述;asset catalog 和 build settings 可以设置配置页的 accent color 和 background color;Intent Definition File 可以让某个参数依赖另一个参数。
configuration UI customization:
configurationDisplayName
description
Global Accent Color Name
Widget Background Color Name
parameter relationship:
Mirror Calendar App = false
-> show Calendar parameter
关键点:
configurationDisplayName和description会显示在 widget 配置相关界面。- 命名颜色放在 widget extension 的 asset catalog 里。
Global Accent Color Name控制 accent color。Widget Background Color Name控制 widget 背面背景色。- 父子参数关系适合 Calendar 例子:关闭 Mirror Calendar App 后,才显示手动选择 Calendar 的参数。
用 intent donation 帮 Smart Stack 学习用户习惯
(19:13)Smart Stack 会根据用户行为把 widget 转到顶部。iOS 14 让 Shortcuts 和 custom intent donations 也能影响 widget 的展示时机。演示里,用户在 App 里查看某张卡的近期消费时,host app 捐赠同一个 ViewRecentPurchasesIntent。
setup:
mark intent eligible for Siri Suggestions
Supported Combinations: Card
host app behavior:
user views recent purchases for AcmeCard
create INInteraction with ViewRecentPurchasesIntent
donate interaction
prediction:
system predicts Card at the learned time
matching configured widget can surface in Smart Stack
关键点:
Intent is eligible for Siri Suggestions让系统可以预测这个 intent。Supported Combinations指定哪些参数对预测有意义。- 只选择 Card 时,Category 不参与匹配,显示 AcmeCard 的 widget 都有机会被转到顶部。
- 同时选择 Card 和 Category 时,只有两个参数都匹配的 widget 才会被系统考虑。
- 捐赠发生在 host app 里,时机是用户实际查看对应信息的时候。
用 TimelineEntryRelevance 标记重要内容
(23:33)系统还会根据 timeline entry 的相关性判断是否展示 widget。TimelineEntryRelevance 包含 score 和 duration。演示把超过 50 美元的消费视为高相关事件,用更高分数告诉系统这条 entry 更值得显示。
TimelineEntry:
date timestamp
rendered view
relevance: TimelineEntryRelevance
TimelineEntryRelevance:
score
duration
score examples:
1.0 -> purchase over $50
0.1 -> minor purchase
0.0 -> no recent purchase
关键点:
score只和同一个 widget 过去提供的分数比较,不和其他 App 的 widget 比较。score小于或等于 0 表示当前没有相关信息,不应该被转到顶部。duration适合比分直播这类有明确时间窗口的内容。duration为 0 时,相关性会持续到下一次收到 relevance。- 如果一次 timeline 更新不想改变相关性,可以把
TimelineEntryRelevance留空。
核心启发
1. 做一个可选择账户的余额 widget
做什么:让用户在 Home Screen 上放多个余额 widget,每个实例显示一张卡、一个账户或一个钱包。
为什么值得做:session 的交易 App 例子就是为不同 Card 创建多个 Recent Purchases 或 Due Date widget。
怎么开始:在 Intent Definition File 里定义账户参数,打开 Dynamic Options,用 provideCardOptionsCollection 返回当前用户的账户列表,再把 widget 改成 IntentConfiguration。
2. 做一个按分类过滤的近期记录 widget
做什么:让用户选择“食品”“交通”“订阅”等分类,widget 只展示对应记录。
为什么值得做:Category 是演示里的第二个参数,默认值是 All,适合从全量记录逐步收窄。
怎么开始:把分类做成 enum 参数,给它设置默认值,再在 IntentTimelineProvider 中用 intent 参数过滤 timeline entry 的数据。
3. 给 Smart Stack 捐赠用户常看的内容
做什么:当用户每天中午查看某个项目、账户或课程时,让系统学习这个习惯,把对应 widget 在 Smart Stack 里提前显示出来。
为什么值得做:transcript 里的 AcmeCard 例子说明,系统会用 donated intent 识别用户常在某个时间寻找的信息。
怎么开始:把配置 widget 的 intent 标记为 Siri Suggestions eligible,设置只包含关键参数的 Supported Combinations,在 host app 里用 INInteraction 捐赠用户刚查看的 intent。
4. 为强时效事件设置 relevance score
做什么:当订单超额、航班登机、比赛开始、暴雨预警这类事件出现时,让 widget 更容易被系统转到顶部。
为什么值得做:TimelineEntryRelevance 的 score 表示 entry 相对于本 widget 历史内容的重要程度,分数高的 entry 更适合 Smart Stack。
怎么开始:先定义一套自己的分数规则,例如无事件为 0、普通更新为 0.1、重要事件为 1,再在 timeline entry 上附加 relevance。
5. 为固定时长的活动设置 duration
做什么:给比赛、会议、直播课、限时促销这类活动设置相关性窗口,活动结束后不再继续占用 Smart Stack 机会。
为什么值得做:session 的篮球 widget 例子把比赛开始到结束作为固定 duration,期间的后续更新可以不改变 relevance。
怎么开始:生成活动开始时的 timeline entry,设置 TimelineEntryRelevance 的 score 和 duration;后续比分或状态更新如果只改 UI,就把 relevance 留空。
关联 Session
- Meet WidgetKit — 先理解 WidgetKit、timeline、Widget Gallery 和基础配置模型。
- Build SwiftUI views for widgets — 继续处理 configurable widget 最终要渲染的 SwiftUI 视图。
- Widgets Code-along, part 3: Advancing timelines — 用 code-along 练习高级 timeline、多 widget 和动态配置。
- Design great widgets — 从设计角度判断哪些信息适合放进 Home Screen widget。
- Design for intelligence: Make friends with “The System” — 扩展理解 Intents、donations 和系统智能如何协作。
评论
GitHub Issues · utterances