大多数浏览器和
Developer App 均支持流媒体播放。
-
为小组件添加配置和智能
当小组件适时地显示在用户的主屏幕或 Today View 中并提供可操作的相关信息时,它将发挥最大的作用。我们将向你展示如何构建可配置的小组件,让用户创建个性化的主屏幕体验,并在人们需要时利用智能系统帮助获得他们想要的东西。了解如何自定义小组件的配置界面,以及如何根据用户行为在 Siri 建议或小组件 Smart Stack 中显示,或者在出现新的及时信息时让系统知道。 有关小组件的更多信息,请观看“Meet WidgetKit”。有关系智能系统的更多信息,请观看“智能设计”专题。
资源
相关视频
WWDC21
WWDC20
-
下载
(你好 WWDC 2020) 你好 欢迎来到 WWDC
(为小组件添加智能与配置) 欢迎来到 “为小组件添加智能与配置”这个话题 我的名字叫 Ian 和我在一起的是我的同事 Kelvin 在这一讲里 我们会向你介绍 如何让小组件变得可调节 以及一个可调节的小组件如何让系统 能更加智能地工作
在 iOS 14 和 macOS Big Sur 里 我们有一个全新的小组件体验 小组件让你的 app 能以激动人心的方式 把新信息呈现给人们
小组件能够存在于比以往更多的地方 它们能作为叠放的一部分 存在于主屏幕 存在于“今天”视图中 以及 macOS 的通知中心里
为那些小组件提供动力的是 WidgetKit WidgetKit 使你能够创建出多个小组件 每个小组件解决其各自的问题 每个小组件能够支持不同的大小和布局 我们来看一个例子
我们做了一个示例 app 来让你看到你的信用卡上的所有交易 它可以让你查看你的消费信息 并跟踪你所有账户的余额 我在这个 app 里最常做的两件事 是查看余额和查看最近的交易 如果能在主屏幕上 一目了然地看到这些信息 那就太好了 所以我们为这个 app 打造了两个小组件
第一个叫做“最近购买” 它显示了你的一张卡上的购买清单 另一个叫“到期日期” 它显示下一次付款的到期日和你的欠款
因为我经常想一次看到一张卡的信息 我们添加了配置来选择显示哪一张卡 我可以通过轻点 “编辑小组件” 然后选择一张卡来改变所要显示的卡
因为我们的小组件是可设置的 现在大家可以创建出多个 不同的“到期日期”小组件 并在每个小组件里显示不同的卡
现在我们来看看今天会说到的内容 首先 我们会说到如何为你的小组件 添加配置的基础知识 接着 我们会谈谈你可以要求用户 添加的信息种类 并介绍如何用 来自你的 app 中的数据填充界面
之后 我们将讨论如何自定义 小组件背面的标题、描述和颜色 最后 我们将介绍 为你的小组件添加配置 为何能使系统更好地预测 在堆栈中显示你的小组件的次数 我们先从最基本的说起 系统的第一部分是小组件扩展 小组件扩展包含 SwiftUI 代码 这会渲染小组件的视觉外观 它们还包含一些关于小组件本身的元数据 (关于 WidgetKit 的更多信息) 在你开始之前 请确认你已经使用 WidgetKit 和 SwiftUI 创建了小组件扩展 如果你还没有这样做 请务必去看“Meet WidgetKit”那一讲
当你的小组件处于可配置的状态 你可以指定哪些选项 要在小组件的背面询问用户 系统就会为你显示这些选项 这些问题被称为参数 这是我们“最近购买”的小组件 它有一个“卡”参数和一个“类别”参数 “卡”参数允许人们选择一张卡片来显示 而“类别”参数可以让人们过滤列表 只包含特定类别的交易 比如食品杂货 如果他们希望的话
为了定义哪些参数被显示 我们使用 intents(意图) 这与你在 app 中添加 对 Siri 和快捷指令的支持时 使用的系统是一样的 一个 intent 包含一个有序的参数列表 你放在 intent 上的每个参数 都会在小组件的配置用户界面中 显示为一行
你可以在 Xcode 中使用意图定义文件 声明你的 intents 这个文件包含了你所有 intents 它们的参数 并指出它们支持系统的哪些部分 通过将这个文件编译到你的 app 中 系统将能够读取你的 intents
一旦你定义了一个 intent Xcode 也会为你生成一个 intent 类别 包含每个参数的属性 对这个小组件来说 我们使用卡和类别属性 建了一个 ViewRecentPurchasesIntent 类
这个 intent 类的实例 将在运行时传递到小组件扩展中 让你的小组件知道用户配置了什么 以及要显示什么 接下来 我们来谈谈 可以添加到 intent 中的参数类型 正如我之前提到的 我们根据 intent 的定义 为你构建小组件配置用户界面 我们支持多种输入类型 我现在就带大家了解一下 当你指定“字符串”作为参数的类型时 配置用户界面会显示一个文本字段 并且会显示一个“Boolean”参数的开关 配置用户界面 也支持一些不同输入机制的数字 对于整数 它支持数域和步进器 对于小数 它支持数域和滑块
配置用户界面还支持联系人和位置选择器 “人员”类型将显示为联系人选择器 “地点”类型将显示为位置选择器
配置用户界面也支持枚举 你可以使这些枚举处于静态模式 或者用你的 app 的内容动态地填充它们 后面我们会详细说到动态选项 配置用户界面也支持其他一些类型 使用各自的用户界面 参数也可以支持多个值 例如 如果你的小组件显示的 是你的日历中的事件列表 你可以配置 intent 以支持选择多个日历 作为 iOS 14 中的新功能 Intents 现在支持固定大小的数组 如果你的小组件支持显示固定数量的项目 这会很有用 它可以让你防止用户向数组中添加 超过定义数量的项目 你可以在 intent 编辑器中 根据小组件大小 指定项目数量 现在我将向你介绍 如何为你的小组件添加丰富的配置 第一步是确定你想配置的对象 让我们用“最近购买”小组件作为例子 在“最近购买”小组件里 每个小组件只能显示一张卡 但是人们在 app 里可能会有多张卡 因此 让这个小组件变得可配置 就很有意义了
这允许人们在主屏幕上 拥有多个“最近购买”的小组件 每个小组件显示不同的卡片 如果能够按类别进行过滤也会很有用 这样一来 人们就可以用一个小组件来显示交通费用 而用另一个小组件来显示食物开销
所以 除了让卡可以配置之外 我们还会让大家对类别进行配置
现在我将为大家介绍我们如何 使“最近购买”的小组件变成可配置状态 这是我们做的项目 我们已经把小组件设置好了 你可以看到小组件当前处于静态配置状态
为了使小组件可配置 我们需要从静态配置 切换到 intent 配置 切换到 intent 配置的第一步 是定义一个 你将用于配置小组件的 intent 你可以在 intent 定义文件中 定义自定义 intent
我在这个项目中已经定义了一个 你会注意到 它在 app 和小组件扩展目标中 都被勾选了
现在让我们用左下角的加号按钮 创建一个 intent
我会把它称为 ViewRecentPurchases
接下来我们要勾选 “intent 符合小组件条件”选项
这将允许 intent 作为小组件的配置 开始运行 如果你想让这个 intent 也支持快捷指令 app 请勾选“intent 在快捷指令 app 中 可由用户配置并添加到 Siri 中”选项 在这个演示中 我们将不勾选这个选项 只关注小组件 我们也将暂时不勾选 “intent 符合 Siri 建议的条件” 这个复选框 我的同事 Kelvin 将在后面的讲座中 向你介绍如何为你的小组件添加智能 我们也会把这个 intent 的类别 设置为“查看” 因为我们的目的是查看你的交易
现在 使用参数列表中的加号按钮 我要为这张卡添加一个参数 这里要做的第一步是给参数命名 此标签将显示在小组件配置用户界面中 我要把它命名为“卡”
接下来 我要选择一个种类
因为信用卡在我的 app 里面 代表了一个对象 所以我要创建一个自定义类型来代表它 你会看到我已经创建了一个“卡”的类别 它有一个名称和标识符 所以我在这里用它来表示我的类型
卡的列表需要由 app 提供 并且会根据登录的人而改变 所以我会勾选 “动态提供选项”的复选框
我们后面会详细介绍 如何填充这个动态列表 由于这个 intent 不支持在 Siri 中运行 我们可以取消勾选 “Siri 在运行时可以问值”选项
其次 因为我们要让大家能够选择类别 我们将在 intent 中添加一个“类别”参数
因为有一组固定的类别 我们可以使用一个枚举 来表示这个参数的类型 我已经定义了一个枚举 所以我就选它了
我们将类别的默认值设置为“全部” 这样 在默认状态下 人们就会看到所有的交易
而且我们还要为这个类别的选项 取消勾选 “Siri 运行时可以询问值”
现在我们来说说动态选项和搜索 在很多情况下 要在小组件配置中显示的数据 可能会因人而异 无法在 intent 定义文件中预先指定 例如 我们的示例 app 中的卡列表 就因人而异 你可以通过使用动态选项来实现
你可以通过在 Xcode 中勾选 “动态选项”复选框 为 intent 中的任何参数启用动态选项 启用动态选项将向系统表明 它应该咨询你的 app 以检索某一个人可以选择的可能值 而不是让他们输入任何他们想要的值 一旦启用了动态选项 就会发生两件事 首先 你的参数的视觉外观 将在小组件的背面 改变为一个按钮 它将打开一个模态的选项列表
其次 将生成两个方法 让你在 app 中实现 一个是提供可能的选项列表 一个是默认值
这些方法是 Xcode 为你生成的 intent 处理协议的一部分 你需要在你的 app 中 或在 Intents 扩展中 创建一个符合此协议的类 当使用者在配置你的小组件时 系统将要求该类提供可能的选项
在示例 app 中 我们需要实现的两个方法 是 provideCardOptionsCollection 和 defaultCard 对于 provideCardOptionsCollection 我们将加载用户设置的卡列表 然后调用完成处理程序 对于 defaultCard 我们返回用户设置的主卡
provideCardOptionsCollection 方法 让你要么提供一份完整的卡列表 要么一份包含卡的部分列表
例如 我们可以为每种类型的卡 做分段显示 如信用卡或借记卡 如果你使用分段 你的用户界面看起来会像这样
现在我所有的信用卡 都显示在“Credit”栏目下 而且我可以看到 更多包含其他类型卡的栏目
默认情况下 顶部的搜索栏会过滤你提供的选项 在某些情况下 相比你在列表中预先提供的数据 你的 app 可能会有更多的数据 如果是这样 你可以在使用者输入时提供搜索结果 这些结果可以包括 你动态提供的标准选项之外的选项
要做到这一点 请务必勾选 “intent 处理程序在用户输入时 提供搜索结果”复选框 并同时提供一个提示
如果勾选该复选框 provideCardOptionsCollection 方法 将获得一个搜索词参数
当使用者第一次看列表时 这个方法会以无搜索词的状态被调用 然后当使用者开始输入时 这个方法会被重新调用 并使用更新的搜索词 现在让我们快速演示一下 如何实现动态选项 继续使用刚才的示例 让我们继续实现将卡列表动态返回给用户 第一步是为 ViewRecentPurchases intent 设置 intent 处理程序 我们将把我们的 intent 处理程序 放在 Intents 扩展中 我已经为我们的另一个小组件 设置了一个 Intents 扩展 所以我可以在那里添加我的代码
下一步是让我们的 intent 处理程序 符合 ViewRecentPurchases intent 处理协议
你可以看到 这个协议只有一个必需的方法 provideCardOptionsCollection 方法 我们需要实现这个方法 使其在 app 内部返回一个卡列表 首先 我从我的 app 内部的对象中 创建自定义的 Card 对象 我把它们放到 INObjectCollection 这让我能够添加部分 如果我想的话
我没有想到要添加的部分 所以我会只从一个项目列表中创建集合 然后用创建的集合调用完成处理程序
还有一个可选的方法是提供一张默认卡
当一个小组件第一次被拖到主屏幕上时 会使用默认值 所以提供一个好的默认值真的很重要
现在我们已经创建了我们的 intent 并实现了我们的 intent 处理程序 我们可以在小组件中采用 intent 配置
这跟我们刚才说到的静态配置 非常相似 但它需要一个 intent 类型作为参数
你还需要把你的 TimelineProvider 切换为 IntentTimelineProvider
它与默认的 TimelineProvider 非常相似 但这些方法有一个额外的 intent 参数 你可以用它来决定要显示的内容
这时候 我们需要从 intent 中 获取卡的信息 并以此来决定显示哪些购买行为 之前只是显示默认卡的消费情况
我们来运行代码并尝试配置小组件
注意 当我拖出小组件时 它显示的是默认卡的交易
这是因为我实现了默认卡的方法
现在我把它翻转过来 然后点击“卡”按钮 它就会显示出一个卡列表
轻点“类别”选项 还可以看到类别列表
好了
现在我们来谈谈进一步定制 你的小组件配置用户界面外观的几种方法 你可以通过使用小组件扩展中 名为“configurationDisplayName” 和“description”的 SwiftUI 修饰符 来自定义标题和描述
接下来是颜色 你可以对小组件配置用户界面的背景 和重点颜色 进行样式设计 以匹配你的 app 的配色方案
要做到这一点 你需要将命名的颜色 添加到你的小组件扩展的 asset catalog 中 在这里 我们要为重点色添加一个 为背景色添加一个
然后你需要将你的颜色名称添加到 你的小组件扩展的构建设置中的 “全局重点颜色名称” 和“小组件背景颜色名称”
你还需要根据另一个参数 来隐藏和显示特定的参数 比方说 在日历小组件中 如果你关闭了“镜像日历 app”的开关 出现“日历”参数 你可以手动选择显示哪些日历
我们来看看 Intent 定义文件 看看如何指定“镜像日历 App”和“日历” 之间的关系
要指定我们只希望 “镜像日历 App”选项关闭时 “日历”参数才会显示出来 请将“镜像日历 App”参数 设为“日历”参数的父级
为此 我们将选择“日历”参数 然后选择“镜像日历 App”作为其父体 那么我们就设置成只有当父值 准确为“false”时才会显示 现在 “日历”参数 只有在关闭“镜像日历 app”的情况下 才会显示出来 我要讲的内容就是这些 现在请 Kelvin 谈谈系统智能和小组件
大家好 我是 Kelvin 我是 Apple 的 Proactive 团队的 Kelvin 接下来 我们要谈一谈系统智能 小组件是横跨 iOS、iPadOS 和 macOS 的 最令人兴奋的新机遇之一 在 iOS 14 上 你不仅可以在主屏幕上添加小组件 还可以将多个小组件堆叠在一起 并通过轻松滑动 在一个地方提供对各种小组件的访问
每个人都会找到不同的方式来利用这一点 但很容易想象 你可以将多个小组件组合在一起 这在你一天的工作过程中会很有用 现在 叠放最让人兴奋的一点 就是系统可以自动将小组件 旋转到堆栈的顶部 以提供有用而及时的信息 (叠放如何智能地工作? 如何在合适的时间出现?) 让我带你了解一下 驱动堆栈智能的基本设计原则 以及你应该如何实现一些新的 API 以确保你的 app 是这种全新的主屏幕体验中的一部分 让我们来深入了解一下 什么才是好的智能叠放 叠放应及时提供让人一目了然 对用户有明显价值的的信息 在你有与使用你的 app 的人 相关的及时信息时 你希望你的小组件能够显现 比如当你知道有雷雨要来的时候 但不只是定期更新温度的时候 大致来说 系统会基于两个原因尝试显现小组件 第一个是基于用户行为的 我们希望为用户显现那些 为他们提供在特定时间内 寻找的信息的小组件 比如说 如果有人经常启动你的天气 app 来查看天气情况 系统可以将该信息显现在你的小组件上 以便更快速地访问他们正在寻找的信息
第二种是基于你的 app 的相关信息 因此 比方说 如果此时雷雨大作 你的小组件会告知系统 它有一个高度相关的更新 系统会考虑将你的小组件 显现到堆栈的顶部
现在让我们来谈谈 你可以使用哪些 API 为系统提供所需的信息 以显现你的小组件
我们先从用户行为说起
所以 当有人像往常一样 在你的 app 中寻找信息时 系统就会希望显现你的小组件 在 iOS 12 中 我们引入了 快捷指令和自定义 intent 捐赠的概念 这为系统提供了一个 了解人们在你的应用中做些什么的方法 使用该信息 系统就会在聚焦中 对用户想执行的动作做出预测 (充分利用用户行为) 现在 在 iOS 14 中的新功能 这些同样的捐赠也会告知系统 什么时候是显现你的小组件的好时机
现在 让我们继续之前的例子 使用“最近购买”的小组件 在这里 我们已经为小组件配置 设置了一个 intent 它允许用户指定信用卡 和他们想要查看的类别 现在 为了让系统智能 旋转到我们的小组件 我们必须为我们的主 app 设置这个相同的捐赠 intent
我们想做到的是 当用户在我们的 app 中 查看某张信用卡时 我们希望通知系统 我们将通过捐赠这个意图来实现这一点 我们稍后会介绍它的实际工作原理 那么现在 我们先来深入了解 关于如何设置的一些细节
首先 我们需要将这个 intent 标记为符合 Siri 建议的条件 这样就可以打开这里最下面的“建议”部分 在我们的示例中 我们希望系统能预测出 某人何时会查看某张信用卡 而且我们希望它能匹配 任何配置了相同卡的小组件 为了表达这一点 我们需要只用卡参数 添加一个“支持的组合”
因此 现在我们已经设置了 自定义 ViewRecentPurchases intent 我们需要每当用户在我们的主 app 中 查看最近的购买时 我们的主 app 就会捐赠它 为此 我们创建一个 INInteraction 对象 并调用捐赠函数 传递我们的意图
而由于我们指定的“支持的组合” 只是卡参数 所以即使我们在捐赠中提供了分类参数 系统也只会考虑卡片参数 这就是你所要做的 系统会完成剩下的工作 现在让我们来仔细看看 系统具体是如何处理你的捐赠的 因此 假设有人在中午 定期查看 我们的 AcmeCard 的杂货购买情况 并在晚上查看 他们的 SoupPay 卡的餐厅购买情况 这时 我们的主 app 会捐出这样的 intents
而根据这些捐赠 系统将认识到 用户通常在中午检查他们的 AcmeCard 而在周五的中午 系统会预测查看 AcmeCard 的 intent 从而显现我们的组件 只要他们将其配置为 显示他们的 AcmeCard 无论类别如何
但是 如果我们同时将卡和类别 添加为支持的组合呢? 我们看看会发生什么 现在 由于类别是支持的组合的一部分 你在告诉系统它是一个重要的参数 然后在周五中午 系统会预测 “杂货”类目中查看 AcmeCard 的 intent 只有在用户明确 配置了这两个参数的情况下 才会显现“杂货”类目的 AcmeCard 小组件
所以 简而言之 “支持的组合”就是向系统传达 哪个可配置的参数真正代表了 人们要找的信息
我们刚刚看到了很多步骤 所以快速总结一下 首先 为你的小组件 设置一个有 intent 的配置 其次 将其标记为符合 Siri 建议的条件 让系统对其进行预测 接下来 只为你希望 系统预测的参数配置“支持的组合” 最后 当用户在你的主 app 里看信息时 捐赠这个 intent 现在我们来说说第二种情况 当你有重要的相关信息时 你希望系统能显现你的小组件
所以 快速总结一下 使用 WidgetKit 你可以提供时间线条目 以决定你的小组件在不同时间点的样子 如果你的小组件可以提前安排你的条目 它的效果会非常好 就像这个天气例子一样 你可以为未来的查阅提供预测 如果你的小组件 需要对新信息作出实时反应 就像我们举的“最近购买”的例子 你只能在每个条目发生时提供它们 它也一样奏效 所以现在假设我们知道 使用我们 app 的人 希望他们在被收取超过50美元的费用时 得到提醒
你如何通知系统 你的小组件有购买 Acme Books 的相关信息? 你可以通过为你的 TimelineEntry 提供一个 TimelineEntryRelevance 对象来传达这些信息
一个 TimelineEntry 实际上有三个组成部分: 一个日期时间戳 它决定了这个条目应该被呈现的时间 应该被呈现的视图 以及这个条目的相关性 相关性是一个 TimelineEntryRelevance 对象 它有两个字段:一个分数和一个持续时间
这就是它在 Swift 中的样子 先说说分数吧 分数是一个数值 表示一个条目 与过去提供的所有条目相比的相关程度 范围和尺度主要由你来定义 因为系统只考虑相对于其他条目的分数 唯一的例外是 零分或更低的分数将向系统表明 你的小组件目前没有相关信息 不应显现 现在 回到我们刚才的例子 我们要向系统传达 当有超过50美元的消费时 我们有重要的信息 当发生这种情况时 我们可以简单地给出一分 以强调重要性 而其他所有的购买都是 0.1 分 这样一来 系统有很小的可能性 会为小额购买显现我们的小组件 但会尽量优先显现大额购买 当没有重要信息的时候 比如我们在早上 8:04 没有最近的购买行为 我们就设置为 0 分 记住 其他小组件提供的分数并不重要 分数只在你提供的分数内进行比较 另一个方面 比方说 我们认为花费的金额 是一个很好的相关性指标 我们可以将消费金额设置为分数 而系统同样会优先显现价格高的采购行为 接下来 我们来谈谈持续的时间 持续时间是一个字段 适用于以下情况 你有一个明确定义的时间段 在这个时间段内 相关性分数将被固定 否则 可以随意将持续时间设为零 这意味着相关性得分 将持续到收到下一个 TimelineEntryRelevance 为止
这里有一个例子来强调如何使用持续时间 我们想建立一个篮球小组件 在比赛进行时显示比赛的进度 所以 在游戏开始时 我们可以创建一个分数为 1 的条目 并且在游戏的长度上有固定的持续时间 在比赛过程中 我们可以在不影响相关性的前提下 继续进行 TimelineEntry 更新 我们只需将 TimelineEntryRelevance 字段设为 0 将该条目设置为 0 就是告诉系统 为了相关性的目的而忽略该更新 所以总结一下 通过智能叠放 我们有机会将你的小组件显现在堆栈之上 你可以用两种办法让你的小组件工作 首先 通过从你的 app 中捐赠 与你的小组件配置相匹配的 intents 第二个办法就是 在你的小组件有重要信息的时候 提供 TimelineEntryRelevance 感谢你的观看 我们迫不及待地想看到你将打造什么样的 可配置的智能小组件
(你好 WWDC 2020)
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。