SiriKit 新变化:让 Intent 更强大

Stella981
• 阅读 1764

作者:wiilen,iOS 开发者。

Sessions: https://developer.apple.com/videos/play/wwdc2020/10073/

今年,苹果为 intent 提供了更强大的 API。本文的重点是如何有效地在 App 中支持 Siri 和 Shortcut 的相关功能,为此工程师提供了几个技巧和策略。

小提示:这个 Session 的字幕有些问题,有一大部分断句断的位置不对,看的时候最好直接听。

内容主要分为两块:

  1. 今年 SiriKit 提供的新 API.

  2. 如何调试自定义的 intent。

先来看看一图简介:

SiriKit 新变化:让 Intent 更强大

总体回顾

SiriKit 中提供了 Intent 和 Intents UI framework,让 App 提供的服务能和 Siri、Shortcuts 及 Maps 等服务融为一体,提供流畅的体验。而在 iOS 14 中,开发者能通过 intents 给 widget 添加配置,并使其更智能。

SiriKit 新变化:让 Intent 更强大

Intents UI extension 能在 Siri Shortcut 或者 Maps 界面中展现自定义的 UI。当 intents extension 完成了用户的请求,它能从 SiriKit 中获取用户的指令,并将其转化为 App 特定的操作,比如发消息、播放音乐、查看当前天气、或者定个外卖。SiriKit 中定义了大量系统级的 Intent,能执行常见操作。对系统级的 Intent 来说,Siri 已经定义好了工作流程,App 只需要提供数据即可完成对应操作。如果你的 App 能让用户执行一些日常的操作,而目前 SiriKit 中并没有提供,那可以创建自定义的 intent 来实现这个操作流程。

SiriKit 新变化:让 Intent 更强大

Intents extension 为 SiriKit 提供 Handler 对象,用来处理特定 intent 。Intent 处理的生命周期:每次用户执行一个 intent,你的 intent handler 都有 10 秒来完成这个请求。10 秒的超时时间从用户的请求初始化并链接到你的 intent extension 时就开始计算了。当这个过程开始时,如果你的 extension 还不在运行,系统会唤起它。Extension 的启动时间取决于载入所有 framework 的时间,以及该程序和它所链接的 framework 调用 load 方法和静态初始化的时间。该 extension 也需要一些时间来执行业务逻辑。

SiriKit 新变化:让 Intent 更强大

所以要优化启动时间,需要让 extension 只链接必要的 framework。处理请求的时间也影响用户使用 App 的感受。使用 Siri 的过程应该是快速简便的,所以在处理 intent 时应该减少用户的等待时间。由于在大部分情况下你的 extension 并不需要链接到所有的 framework,你就可以减少需要引入的 symbol。对于 intent extension,值得一提的是比起 App 来它们的执行过程相对独立,运行内存也较少。

In-app intent 处理

在 iOS 14 中,有时候无法使用 extension,或者用起来很麻烦。这次苹果提出了新的 in-app intent 处理。如今开发者可以选择将 intent handler 加入到 App 中,处理 SiriKit 中的请求。

SiriKit 新变化:让 Intent 更强大

适合 in-app intent 处理的场景

  1. 控制音乐播放、开始运动等 intent 之前需要先在 extension 中处理,然后再交给 App。如今直接在 App 中处理会更有效率。

  2. 处理 intent 的结果会影响当前 App 的 UI,这种 intent 也适合放在 App 中处理。

  3. 需要大量内存的场景,比如原先受 extension 内存限制无法实现的图片和视频处理。

  4. app 架构导致无法把代码抽出来放到 extension 中,或放到一个共享的 framework。要小心,App 的启动时间也会包含在 10 秒的超时时间内。

如何实现 in-app intent handler

  1. 首先要确认 App 支持多 window,并适配了 UIScene lifecycle。当 App 因 SiriKit 请求被唤起时,还没有 UIScene 对象连接到 App。

SiriKit 新变化:让 Intent 更强大

  1. 然后你需要在 App target 的 support intents section 下列出所有你想要在 App 中处理的 intent。

SiriKit 新变化:让 Intent 更强大

  1. 最后,你需要在 AppDelagate 中实现 handlerForIntent: 方法。这个方法作为调度中心,将 intent 分发给能够处理它的对象。在具体实现中,先检查 intent 的类型,然后返回能够处理它的对象。这个对象必须实现了用于处理该 intent 的协议。

SiriKit 新变化:让 Intent 更强大

如果需要用户使用 intent 之前正在操作 App,才能在处理该 intent 时更新相关 UI,那么 intent handler 就需要确保在处理过程中相关的 UI 仍在屏幕上。这可以通过检查 App 是否在后台来实现,如果 App 在后台,就需要返回 continueInApp 来让系统打开 App。

SiriKit 新变化:让 Intent 更强大

实现演示

演示的 App 主要用于浏览食谱,点击 direction 按钮时,可以分步骤浏览食谱。当要准备做饭,操作 App 就不太方便,所以就希望用户能够用语音唤起 Siri,执行 shortcut 来查看下一步的操作。由于需要和屏幕上的内容做交互,这里选择了 in-app intent 的实现方式。

接下来工程师演示了添加过程,从 07:57 开始,建议这里直接观看 demo 来学习,实现的步骤和上文中所述一致。

这里有几个要点可以参考:

  1. 检查 multiple window 的支持,以及添加 intent 到 App Target 中。

SiriKit 新变化:让 Intent 更强大

  1. 由于希望 App 中的每一个 view controller 都能响应 nextStep 这个 command,所以定义了一个通用的 IntentHandler 类,初始化方法接收一个实现了 NextStepProviding 协议的对象以及一个 Recipe 对象。如果 view controller 实现了这个协议,就需要提供一个 IntentHandler 的实例,并且需要实现 nextStep 方法来让用户进入下一步。

SiriKit 新变化:让 Intent 更强大

IntentHandler 遵守 ShowDirectionsIntentHandling 协议,在 resolve 方法中,我们检查是否有 Recipe 对象来决定下一步怎么走。在 handle 方法中,首先要确认 App 在前台,这一点之前也提到了。如果需要唤起 App,需要在 UIScene Delegate 中处理。

SiriKit 新变化:让 Intent 更强大

  1. 由于需要引用 IntentHandler 对象,demo 使用了单例来弱引用,在 viewDidAppear: 方法中更新对应的引用。然后在 AppDelegate 中,实现新的 handlerForIntent: 方法,并返回单例中持有的 IntentHandler

SiriKit 新变化:让 Intent 更强大

而在 SceneDelegate 中,需要实现 willConnectToSession:continueUserActivity: 两个代理方法,用于在 handle 方法返回了 continueInApp 之后继续处理 user activity。当还没有 UIScene 对象连接到 App 时,willConnectToSession: 方法会被调用。

SiriKit 新变化:让 Intent 更强大

  1. 让所有的 view controller 实现 NextStepProviding 协议,然后在 viewDidAppear: 更新 currentIntentHandler

SiriKit 新变化:让 Intent 更强大

一般来说在 extension 中处理 intent 是更好的选择。有以下几个理由:

  1. Intent extension 更轻量,启动更快。

  2. 通过评估要链接的 framework 数量来优化启动时间。

In-app intent handling 总结

  1. 优先考虑使用 intent extension。

  2. 谨慎选择 App 所链接的 framework。

3 .In-app intent handling 需要 App 支持 multiple windows。(此处可以参考 WWDC 19 关于多 window 介绍的两个视频)

  1. In-app intent handling 可以用于处理新场景下的任务。

更丰富的歧义消除功能

在 iOS 13 中,苹果为 Shortcuts 引入了新的功能,可以让用户在运行时提供参数来帮助处理 intent。通过返回一个用于消除歧义的解析结果,用户可以从弹出的列表中选择一个作为 intent 的参数。今年你可以为这个列表添加副标题和图片了,只需要在运行时提供 String 类型的副标题和 INImage 类型的图片。在 Shortcuts App 中配置 intent 时,你也可以提供带有图片和副标题的选项。

SiriKit 新变化:让 Intent 更强大

为消除歧义列表添加的另一个功能是分页。作为一名开发者,现在你可以指定 Siri 一次性可以朗读的选项数目,也可以指定子项目中的引导词。只有用户用 Hey Siri 唤醒时,这种多级分页才会启用。

SiriKit 新变化:让 Intent 更强大

在自定义 intent 的文件中,对需要自定义分页的 intent,展开 Siri dialog,在这里你可以指定 Siri 一次性可以读给用户的选项数目。就像你可以指定子项目的引导词一样,你也可以覆盖 Siri 提供的消除歧义的引导词,提供个性化的词句。

SiriKit 新变化:让 Intent 更强大

去年,苹果提供了动态选项的 API,让你可以在用户配置 intent 时为其提供合适的选项。今年的新 API 允许用户在配置 intent 时搜索可用选项。在自定义 intent 的文件中,Dynamic Options 栏下,有一个新的勾选框,勾上之后用户就可以搜索可用的选项。

SiriKit 新变化:让 Intent 更强大

勾选之后会生成一个新的方法,方法入参中含有用户的搜索词。用户在输入时,这个方法会不断被调用。当搜索词为空,你也可以为用户提供默认搜索词。Dynamic Search 只适合搜索大量的选项时使用,而不建议用于过滤少量的静态选项,这是因为 Shortcuts App 默认就支持过滤。

SiriKit 新变化:让 Intent 更强大

提供选项的 completion handler 中有一个新的类型 INObjectCollection,有了这个类型,你可以将选项按段划分,提供标题,并可以选择按索引来排序。

SiriKit 新变化:让 Intent 更强大

在 iOS 13 中,苹果为 Shortcuts 引入了可配置的参数,所有配置为用户输入的参数必须一次性解析完。在 iOS 14,现在可以分开配置和解析这些参数了。Siri 和 Shortcuts App 不会解析被标记为 unresolvable 的参数。

SiriKit 新变化:让 Intent 更强大

一些小建议

  1. 如果你有一些自定义的 intent,由于相关功能不再维护而不再使用了,或者你用另外一个 intent 替代了它,在 iOS 14 中你可以把这个 intent 标记为 deprecated。标记之后,用户就可以看到这个 intent 在将来不可用的提示了,且 Shortcuts App 中也无法再从动作列表选择该动作。

SiriKit 新变化:让 Intent 更强大

  1. 关于如何指定自定义 intent 的类名。当你在 intent 文件的 custom intent 中添加了 intent 的类型或者是自定义 enum 时,实际上添加的是类型的名称而不是具体的类型。具体的类型会根据类型名字来自动生成。这个地方并不是用来指定 intent 的类型和 enum的。

SiriKit 新变化:让 Intent 更强大

应该在 custom class inspector 中指定类型。

SiriKit 新变化:让 Intent 更强大

或者你也可以在 target 的项目文件中,为自定义的 intent 类型和 enum 指定类前缀。

SiriKit 新变化:让 Intent 更强大

  1. 如何高效管理多个 intent 和 intent UI extension。当往 intent UI extenstion 中添加 intent 定义文件时,Xcode 会自动列出所有该 intent UI extension 支持的 intent,然而有些 intent 你可能不想让它显示 UI。这时可以创建一个新的 intent 定义文件,加入非 UI 的 intent。然后在 intent 定义文件的 target membership Inspector,不将其加入 intent UI extension target。

SiriKit 新变化:让 Intent 更强大

  1. 选择生成代码的语言。在 project 的 build setting 中修改即可。

SiriKit 新变化:让 Intent 更强大

推荐阅读

当 Widget 遇到智能化

SiriKit 新变化:高品质的 Siri 媒体交互

关注我们

我们是「老司机技术周报」,每周会发布一份关于 iOS 的周报,也会定期分享一些和 iOS 相关的技术。欢迎关注。

SiriKit 新变化:让 Intent 更强大

关注有礼,关注【老司机技术周报】,回复「2020」,领取学习大礼包。

支持作者

这篇文章的内容来自于 《WWDC20 内参》。在这里给大家推荐一下这个专栏,专栏目前已经创作了 108 篇文章,只需要 29.9 元。点击【阅读原文】,就可以购买继续阅读 ~

WWDC 内参 系列是由老司机周报、知识小集合以及 SwiftGG 几个技术组织发起的。已经做了几年了,口碑一直不错。 主要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实际开发经验、苹果文档和视频内容做二次创作。

本文分享自微信公众号 - 老司机技术周报(LSJCoding)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这