SiriKit框架详细解析(六) —— 编程指南之确认和处理请求、指定自定义词汇表和界面(一)

版本记录

版本号 时间
V1.0 2018.09.12

前言

大家都知道随着人工智能的发展,会掀起来另外一个工业革命,而语音识别就是人工智能的初始阶段,但是每个公司做的都不一样,涉及到一系列的语音的采集和算法实现,苹果的Siri就是业界语音识别的代表性的产品。接下来的几篇我们就详细解析一下SiriKit这个框架。感兴趣的可以看下面几篇文章。
1. SiriKit框架详细解析(一)—— 基本概览(一)
2. SiriKit框架详细解析(二)—— 请求授权使用SiriKit和INPreferences类(一)
3. SiriKit框架详细解析(三)—— 创建Intents App扩展(一)
4. SiriKit框架详细解析(四)—— 构建代码以支持App扩展和将意图调度到处理对象(一)
5. SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一)

Confirming a Request - 确认请求

在令人满意地解析了意图的所有参数之后,要求处理程序确认意图的细节并提出响应。当所有参数都已成功解析或不需要继续进行时,所有参数的满意解析都会发生。在确认期间,您可以对所有意图参数执行其他验证,确保您可以使用该信息来执行所请求的服务。

不需要在处理程序中实现确认方法,但强烈建议使用。 Siri始终提示用户确认重要请求,尤其是那些不可撤销或涉及金融交易的请求。 Siri可能会或可能不会在其他情况下提示用户。无论哪种方式,实施确认方法都是确保您能够提供响应的好方法。

Listing 3-2显示了一个用于开始锻炼的简单确认方法。确认方法的主要工作是使用响应对象执行提供的完成块。此示例创建一个响应对象,指示可以成功启动锻炼。如果要执行任何其他验证,可以使用此方法执行此操作。

// Listing 3-2 Confirming the start of a workout

// OC
- (void)confirmStartWorkout:(INStartWorkoutIntent *)startWorkoutIntent
completion:(void (^)(INStartWorkoutIntentResponse * _Nonnull))completion 
{
    NSUserActivity *activity = [[NSUserActivity alloc]
    initWithActivityType:@"startWorkoutActivityType"];
    INStartWorkoutIntentResponse* response =  [[INStartWorkoutIntentResponse alloc] initWithCode:INStartWorkoutIntentResponseCodeSuccess userActivity:activity];
    // Perform any final validation.
    completion(response);
}
//Swift
func confirmStartWorkout(startWorkout intent: INStartWorkoutIntent,
completion: (INStartWorkoutIntentResponse) -> Void) 
{
    let activity = NSUserActivity(activityType: "startWorkoutActivityType")
    let response = INStartWorkoutIntentResponse(code: .success, userActivity: activity)
    // Perform any final validation.
    completion(response)
}

有关为每个intent创建的响应对象的信息,请参阅Intents Domains


Handling a Request - 处理请求

处理意图的最后阶段是执行与该意图相关联的操作。处理程序对象的handle方法有两个职责:

  • 执行与意图相关的任务。
  • 返回一个响应对象,其中包含有关您的应用程序执行了什么。

处理任务时,请连接到您的服务并执行相关任务。执行任务的实施细节完全由您负责。例如,乘车预订服务将连接到公司的Web服务器以发出乘车请求并返回结果。

除了执行任务外,还要创建一个包含所执行操作详细信息的响应对象。您放入响应对象的信息因每个意图而异,某些响应对象可能需要比其他更多的信息。您还应该为NSUserActivity对象提供应用程序可能需要继续执行任务的任何其他详细信息。用户可能会选择立即启动您的应用以获取更多详细信息。如果发生这种情况,用户活动对象应包含使用任务详细信息配置应用程序界面所需的任何信息。

Listing 3-3显示了一个handle方法,用于报告新启动的锻炼的状态。在此示例中,处理程序调用自定义方法,该方法在返回对Siri的响应之前通知应用程序启动指定的锻炼。

// Listing 3-3 Handling the start of a workout

// OC
- (void)handleStartWorkout:(INStartWorkoutIntent *)startWorkoutIntent
completion:(void (^) (INStartWorkoutIntentResponse * _Nonnull))completion 
{
    NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:@"startWorkoutActivityType"];
    INStartWorkoutIntentResponse* response = [[INStartWorkoutIntentResponse alloc] initWithCode:INStartWorkoutIntentResponseCodeSuccess userActivity:activity];
    // Do the work…
    [self startWorkoutWithName:startWorkoutIntent.workoutName];
    completion(response);
}
//Swift
func handleStartWorkout(startWorkout intent: INStartWorkoutIntent,
completion: (INStartWorkoutIntentResponse) -> Void) 
{
    let activity = NSUserActivity(activityType: "startWorkoutActivityType")
    let response = INStartWorkoutIntentResponse(code: .success, userActivity: activity)
    // Do the work…
    self.startWorkout(startWorkoutIntent.workoutName!)
    completion(response)
}

您在Intents扩展中所做的更改也应反映在iOS应用的界面中。 作为处理任务的一部分,您的扩展程序应该为您的iOS应用程序提供任何所需的数据。 即使您可以为INInteraction对象提供intent和响应的详细信息,但在所有情况下,用户活动对象都不会传递到您的应用程序。 例如,用户可以在不使用Handoff的情况下启动应用程序。 为确保您的应用是最新的,您的扩展程序可以将任何更新的文件放在您的应用可访问的共享组容器中。 然后,您的应用可以使用后台应用刷新机会来获取任何更改并自行更新。

有关为每个intent创建的响应对象的信息,请参阅Intents Domains


Specifying Custom Vocabulary - 指定自定义词汇表

拥有自定义词汇表的应用程序可以告知Siri正确使用该词汇表。 自定义词汇是指Siri可能无法理解的任何术语。 例如,将特定车辆类型称为“Vroom”的乘车预订应用程序可以为Siri定义该术语并提供用户如何使用它的示例。 定义应用程序的词汇表可为Siri提供有关理解与应用程序相关的用户命令的提示,并有助于改善整体用户体验。

有两种方法可以定义应用程序的自定义词汇表:

  • 要注册特定于单个用户的术语,请使用INVocabulary对象。
  • 要注册应用程序的所有用户共有的术语,请将AppIntentVocabulary.plist文件添加到iOS应用程序。

重要:Siri将自定义词汇表视为提示,尽可能多地结合您的自定义术语。 但是,自定义术语的空间有限,因此请务必仅注册其使用可能会造成混淆的术语,并保持注册术语的总数尽可能小。

1. Registering User-Specific Vocabulary Terms - 注册用户特定词汇术语

使用共享的INVocabulary对象来注册特定于单个用户的词汇表。用户特定术语必须属于以下类别之一:

  • 联系人姓名(仅当他们不是由Contacts框架管理时)
  • 照片标签
  • 相册名称
  • 锻炼名称

选择要注册的词汇表时,请选择不熟悉您的应用程序的人可能会误解的词汇。例如,消息传递应用程序可能会从用户的收藏夹列表中注册屏幕名称。不要注册易于理解的术语,例如“我的相册”或“我的锻炼”。相反,请关注其字面含义与应用程序对这些术语的使用不同的术语。

您可以使用setVocabularyStrings:ofType:方法为每个类别注册术语集。注册一组新术语将替换该类别的先前术语,因此请在每次调用该方法时包含所需的所有术语。不要包括所有可用的术语。相反,请关注与用户收藏夹相关的术语,频繁使用的术语或最近使用的术语。最重要的术语应始终位于您创建的NSOrderedSet对象中。

Listing 4-1显示了一个注册一组自定义训练的示例。 该应用程序根据最后一次使用锻炼名称对锻炼名称进行分类,将最近使用的锻炼放在有序集合中。 通常,您从应用程序注册特定于用户的术语,而不是从Intents扩展注册。

//Listing 4-1 Registering user-specific vocabulary

//OC
NSOrderedSet* workoutNames = [self sortedWorkoutNames];
INVocabulary* vocabulary = [INVocabulary sharedVocabulary];
[vocabulary setVocabularyStrings:workoutNames ofType:INVocabularyStringTypeWorkoutActivityName];
//Swift
let workoutNames = self.sortedWorkoutNames()
let vocabulary = INVocabulary.shared()
vocabulary.setVocabularyStrings(workoutNames, of:.workoutActivityName)

注册一组术语并不能保证Siri稍后会认可它们。 Siri会将您提供的任何条款视为提示,并在可能的情况下使用它们。 因此,重点关注应用程序对您的应用程序以及特定用户和实际使用的用途所特有的术语。 不要包含用户在与Siri交谈时永远不会使用的通用术语或术语。

有关注册用户特定词汇表术语的其他信息,请参阅INVocabulary Class Reference

2. Creating the Global Vocabulary File - 创建全局词汇文件

使用全局词汇表文件来注册应用程序的所有用户共有的词汇表。 全局术语必须属于以下类别之一:

  • 乘车选择
  • 锻炼名称

全局词汇表文件是名为AppIntentVocabulary.plist的属性列表文件。 将此文件放在与应用程序的基本开发语言对应的.lproj目录中。 在应用程序的特定于语言的项目(.lproj)目录中包含本地化版本。 在Xcode中,您可以从“文件”检查器自动创建本地化版本。

To create the global vocabulary file - 创建全局词汇表文件

  • 1) 选择New > File
  • 2) 在iOS > Resource中,选择属性列表文件类型。
  • 3) 点击Next
  • 4) 将文件名设置为AppIntentVocabulary.plist
  • 5) 单击Create
  • 6) 在项目中选择AppIntentVocabulary.plist文件。
  • 7) 在Root元素下添加两个键。
    • 将第一个键的名称设置为ParameterVocabularyies
    • 将第二个键的名称设置为IntentPhrases

全局词汇表文件在根级别包含两个键:

  • ParameterVocabularyies键定义应用程序的自定义术语及其应用的intent参数。
  • IntentPhrases键包含包含您的自定义术语的示例短语。

对于每个自定义术语,请指定该术语适用的术语和intent属性。单个术语可以与多个意图相关联。例如,自定义锻炼名称可以同等地应用于所有其他与锻炼相关的意图类别。除了术语和意图信息之外,还可以指定SiriKit的标识符字符串以放置在intent对象中。在解决过程中,您可以将该标识符字符串解析为适当的锻炼。

重要:在开发过程中,Xcode会将您的全局词汇转发给Siri,但会限制该词汇表对您的开发设备的可用性。 摄取词汇数据不是即时的,因此在测试任何自定义词汇表之前,您可能需要等待一两分钟。

有关全局词汇表文件的结构和键的详细信息,请参阅App Vocabulary File Format


Providing a Custom Interface - 提供自定义界面

Siri和Maps应用程序显示Intents扩展程序提供的信息,但您可以使用Intents UI扩展程序自定义部分显示内容。Intents UI扩展的目的是自定义Siri或Maps界面,以便用户知道您的应用程序正在提供响应。例如,您可以添加与您的brand相关的可视元素,或者提供与请求相关但不是标准界面的其他信息。

Intents UI扩展包含一个视图控制器,您可以使用该视图控制器填充与应用程序响应相关的信息。您可以显示应用程序支持的任何或所有意图的自定义信息。当显示对支持的意图的响应时,Siri和Maps将您的Intents UI扩展中的视图控制器集成到它们显示的界面中。使用传递给视图控制器的响应数据来配置任何视图的内容并确定要显示的内容。您可以显示与您的品牌相关或对用户有用的任何信息。您可能无法展示广告。

您可以提供Intents UI扩展,以支持与预订,消息,付款和健身相关的意图。有关如何使用Intents UI扩展的一些示例包括:

  • Ride booking - 乘车预订。显示其他骑行细节和品牌。
  • Messages - 消息。使用您的品牌颜色和样式显示消息内容。
  • Payments - 付款。显示品牌或其他与付款相关的信息。
  • Fitness - 健身。显示自定义锻炼信息。

Intents UI扩展可能支持多个意图,但所有这些意图共享相同的视图控制器。 您的视图控制器会根据当前意图和显示环境接收足够的信息来自行配置。 大多数意图由Siri显示,但乘坐预订意图通常由Maps应用程序显示。

1. Configuring Your Xcode Project - 配置Xcode项目

要自定义Siri界面,请在iOS应用程序中添加Intents UI扩展。 您可以在创建Intents扩展时添加此扩展,也可以稍后将其添加到项目中。

To add a new Intents UI extension to your app - 向您的应用添加新的Intents UI扩展

  • 1) 在Xcode中打开现有的iOS应用程序项目。
  • 2) 选择File > New > Target
  • 3) 从iOS Application Extension组中选择Intents UI扩展。
  • 4) 点击Next
  • 5) 指定扩展名称并配置语言和其他选项。
  • 6) 单击Finish

Xcode提供的Intents UI扩展模板包含一个带有单个视图控制器的故事板。 Siri和Maps始终在故事板文件中加载并显示初始视图控制器,因此请使用您要显示的内容配置该视图控制器。 如果要为每个intent显示不同的视图集,请创建子视图控制器并在运行时将它们嵌入到初始视图控制器中。

Intents UI扩展的Info.plist文件告诉Siri您的扩展支持哪些意图。 表5-1列出了扩展的Info.plist文件中NSExtension键字典中必须包含的键。 您可以在NSExtensionAttributes键的字典中指定支持的意图。

Table 5-1 Keys for the Info.plist file of an Intents UI extension

Key Description
NSExtensionAttributes 与此键关联的字典必须包含IntentsSupported键,其值为字符串数组。 每个字符串的值是扩展支持的intent类的名称。
NSExtensionMainStoryboard 此键的值是包含扩展程序视图控制器的Storyboard文件的名称。 如果您希望系统以编程方式创建视图控制器,则可以将NSExtensionPrincipalClass键替换为此键。
NSExtensionPointIdentifier 此键的值必须是字符串com.apple.intents-ui-service

To specify the intents that your custom interface supports - 指定自定义接口支持的意图

  • 1) 在Xcode中,选择Intents扩展的Info.plist文件。
  • 2) 展开NSExtensionNSExtensionAttributes键以查看IntentsSupported键。
  • 3) 在IntentsSupported键中,为您支持的每个意图添加项目。 每个项的类型必须是String,并且值必须是intent的类名。

2. Implementing Your View Controller - 实现View Controller

Intents UI扩展的故事板的初始视图控制器负责显示您的内容。在显示响应之前,Siri或Maps应用程序加载该视图控制器并调用其configureWithInteraction:context:completion:方法。使用该方法中的交互对象配置视图控制器的内容并使其准备好显示在屏幕上。使用context参数根据Siri或Maps界面的需要调整内容的显示。

在屏幕上,视图控制器仍然是前台界面的一部分,直到用户移除Siri或Maps界面。您可以根据需要使用计时器或其他编程方式更新视图控制器的界面,并且视图控制器在加载,显示和隐藏时参与普通视图控制器进程。但是,视图控制器在屏幕上时不会接收触摸事件和其他响应者链事件,并且您无法添加手势识别器或尝试以其他方式拦截事件。因此,您不应该包含需要用户交互的控件或视图。

图5-1显示了Intents UI扩展及其视图控制器的生命周期。系统创建视图控制器并调用其configureWithInteraction:context:completion:方法,向其传递配置界面所需的交互对象。配置完成后,您的视图控制器将显示在屏幕上,其中包含Siri或地图的其他内容。在屏幕上,您的视图控制器可以使用计时器和其他编程方式运行动画并更新自身,但它不会接收触摸事件或响应者链事件。

Figure 5-1 Life cycle of an Intents UI extension

当用户关闭Siri或Maps界面时,系统会释放对视图控制器和Intents UI扩展的引用。视图控制器应仅用于显示信息。当视图控制器移出屏幕时,请勿尝试保存数据或与应用程序通信。

以下是为Intents UI扩展实现视图控制器的一些提示:

  • Incorporate your brand into your interface - 将您的brand融入您的界面。使用应用程序的颜色,图像和其他设计元素是增加熟悉度并传达应用程序存在的好方法。

  • Use child view controllers to switch between different types of content - 使用子视图控制器在不同类型的内容之间切换。您的Intents UI扩展只有一个主视图控制器。如果为不同的意图显示不同的内容,请使用子视图控制器来管理与该意图相关的视图。在configureWithInteraction:context:completion:方法中,根据提供的intent对象安装子视图控制器。

  • Configure any animated content to run only when your view controller is visible - 配置任何动画内容仅在视图控制器可见时运行。等到视图控制器的viewDidAppear:方法被调用以启动动画。在视图控制器的viewWillDisappear:方法中停止动画。

  • Configure your view controller’s view as quickly as possible so that Siri can display it - 尽快配置视图控制器的视图,以便Siri可以显示它。您的视图控制器可能不会在屏幕上显示很长时间,因此请为您的大部分配置使用本地资源和提供的INInteraction对象。如果需要从服务器获取更多信息,请始终异步执行此操作并稍后更新您的界面。

  • Do not include advertising in your interface - 不要在界面中添加广告。您可以包含与用户相关的品牌和信息,但禁止广告。

有关配置视图控制器的更多信息,请参阅NUIHostedViewControlling Protocol Reference

3. Replacing the Default Interface - 替换默认界面

对于乘车预订和消息意图,您可以隐藏系统提供的默认内容(如果它与您提供的内容冲突)。 对于消息意图,Siri显示消息内容和收件人。 对于乘车预订意图,Siri和Maps应用程序会显示一个显示用户位置的地图。 如果为自己的界面提供相同的信息,请使用INUIHostedViewSiriProviding协议的属性来禁止显示系统界面。

有关抑制默认地图和消息信息的详细信息,请参阅INUIHostedViewSiriProviding Protocol Reference

后记

本篇主要讲述了编程指南之确认和处理请求、指定自定义词汇表和界面,感兴趣的给个赞或者关注~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容