版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.12.06 星期四 |
前言
大家都知道随着人工智能的发展,会掀起来另外一个工业革命,而语音识别就是人工智能的初始阶段,但是每个公司做的都不一样,涉及到一系列的语音的采集和算法实现,苹果的Siri就是业界语音识别的代表性的产品。接下来的几篇我们就详细解析一下SiriKit这个框架。感兴趣的可以看下面几篇文章。
1. SiriKit框架详细解析(一)—— 基本概览(一)
2. SiriKit框架详细解析(二)—— 请求授权使用SiriKit和INPreferences类(一)
3. SiriKit框架详细解析(三)—— 创建Intents App扩展(一)
4. SiriKit框架详细解析(四)—— 构建代码以支持App扩展和将意图调度到处理对象(一)
5. SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一)
6. SiriKit框架详细解析(六) —— 编程指南之确认和处理请求、指定自定义词汇表和界面(一)
7. SiriKit框架详细解析(七) —— 构建Siri Shortcuts简单示例(一)
Publishing Articles with Siri
接下来,您希望添加发布直接从Siri编写的文章的功能。 这里的最大区别在于,不是Siri打开你的应用程序,一切都将直接来自Siri UI
。
对于此快捷方式,您将创建一个自定义Intent
来定义Siri,您的用户和您的应用之间的来回。
1. Defining a Custom Writing Intent
在项目导航器中,找到ArticleKit
文件夹并单击它以突出显示它。
然后,按Command + N
创建一个新文件。
在过滤器搜索框中,键入Intent
,您将看到SiriKit Intent Definition File
。
单击Next
,然后将文件命名为ArticleIntents.intentdefinition
。
现在是时候创建一个发布你写的文章的intent
了。
转到读取No Intents
的部分的底部,然后单击加号按钮以添加新的intent
意图。
将其命名为PostArticle
,然后根据这些设置配置您的意图(在图片后面描述):
此屏幕用于配置发布intent
需要处理的信息。
Custom Intent
部分中的选项定义了它的意图类型,并且可以影响Siri如何处理该操作。 告诉Siri这是一个Post
类型动作让系统知道你在某处分享了一些内容:
- 1) Category:
Post
- 2) Title:
Post Article
- 3) Description:
Post the last article
- 4) Default Image:
Select one of the existing images in the project
- 5) Confirmation:
Check this box since you want to ask the user to verify that they’re really ready to publish this article
Parameters
部分用于定义Title
和Subtitle
中使用的任何动态属性,您现在可以使用这些属性。
定义一个名为article
的参数,它是一个Custom
数据类型,一个是类型为String
的publishDate
。
然后,在Shortcut Types
部分中,单击加号按钮以添加一个包含article
和publishDate
参数作为其参数的类型。
接下来,设置快捷方式的Title
和Subtitle
。
将标题设置为Post “${article}”
和副标题设置为on ${publishDate}
。 如果您不复制和粘贴,请确保让Xcode自动完成article
和publishDate
。
最后,确保选中Supports background execution
,这样您就不会被迫离开Siri UI
。
2. Setting Up Siri’s Responses
单击Response
,您可以定义Siri将如何响应用户。
再次,配置您的响应,如下所示:
在Properties
下,您可以再次定义Siri所说的动态部分。 添加title
,publishDate
和failureReason
的属性;把它们都定义为字符串。
然后,在Response Templates
下,为failure
添加此模板:
Sorry, but I couldn't post your article. ${failureReason}
为成功添加以下模板
Your article "${title}" was successfully posted on ${publishDate}. Nice work!
3. Adding a Siri Extension
为了能够在不启动应用程序的情况下继续使用Siri的UI,您需要使用可以管理交互的代码创建Intents Extension
。
单击左上角的项目文件,然后找到允许您添加新目标的加号。
现在,找到Intents Extension
目标;您可以在过滤搜索栏中搜索它。
然后,将您的意图扩展名为WritingIntents
,将Starting Point
设置为None
,并取消选中Include UI Extension
选项。
最后,单击Finish
按钮以创建扩展。 构建并运行以确保事情仍然有效。
注意:当Xcode提供激活
WritingIntents
方案时,单击Cancel
。
没什么新鲜的,但现在你已经准备好使用你的custom intents
了!
在继续之前,您需要做两件快速的事情。
首先,确保扩展名中可以看到ArticleIntents.intentdefinition
。
打开文件,然后查看File inspector
。 确保其Target Membership
包括应用程序,框架和扩展。 此外,请确保将应用程序和扩展目标的代码生成选项更改为No Generated Classes
,因为此代码应存在于框架中。
接下来,您的扩展程序和主应用程序需要共享一个应用程序组。 由于文章保存到磁盘并从磁盘加载,因此这是两个目标在文件系统上共享同一区域的唯一方法。
单击Project
导航器中的项目文件,确保选择了TheBurgeoningWriter
并转到Capabilities
选项卡。
将App Groups
功能切换为ON
,并命名组为group.<your-bundle-id>
。
接下来,选择WritingIntents
扩展并执行相同的操作。 这一次,该组应该存在,因此您可以只检查该框。
最后,打开ArticleManager.swift
并找到groupIdentifier
的声明。 更改其值以匹配新定义的应用程序组名称。
注意:此更改后,您输入的先前文章将不再显示在应用中。 这是预期的,因为它们存储在文件系统中的不同位置。
4. Donating Post Article Intents
现在您已经定义了发布文章的intent
,现在是时候在适当的时候创建和提交一个。
再一次,前往Article.swift
,这样你就可以添加一种方法来为新文章生成“post”
的intents
。
在newArticleShortcut(thumbnail :)
的定义下方,添加以下方法定义:
public func donatePublishIntent() {
}
此方法一次创建并提供intent
,因为您不需要处理向视图控制器添加intents
。
现在,创建intent
对象并分配article and publish date
:
let intent = PostArticleIntent()
intent.article = INObject(identifier: self.title, display: self.title)
intent.publishDate = formattedDate()
当使用自定义intent
时,您最终提交给系统的事情就是这样的交互。
最后,通过在交互上调用donate(_ :)
来提交:
interaction.donate(completion: nil)
在这里,您将提交您的互动,而不必担心completion
块。 当然,您可以将错误处理或其他任何内容添加到此完成块中。
您必须完成最后一次“secret handshake”
步骤:您必须告诉iOS确切的应用程序支持的intents
。 为此,请单击Project
导航器中的项目文件。 选择WritingIntents
目标,然后单击Info
选项卡。 按住Option
键并单击NSExtension
键旁边的显示三角形以打开整个键。 将鼠标悬停在IntentsSupported
上以显示加号按钮并单击一次。 将新添加的项的值设置为PostArticleIntent
。
这就是向系统提交intent-based
的快捷方式的全部内容。
现在您已经定义了方法,转到NewArticleViewController.swift
并找到saveWasTapped()
。 由于您希望系统提示用户发布他们以后保存的文章,因此您可以在这里实现。
添加此行以在该方法中的注释下方提交intent
:
article.donatePublishIntent()
现在您正在提交,构建和运行应用程序。 然后,创建并保存新文章。 完成后,转到Spotlight
搜索,您应该会看到一个类似于此的新提交。
5. Handling Intents-Based Shortcuts
像以前一样,您现在必须考虑在用户使用它时处理此快捷方式。
这一次,您创建的扩展将负责处理事物。
首先,在名为PostArticleIntentHandler.swift
的WritingIntents
文件夹中添加一个新的Swift
文件。
用以下内容替换import Foundation
:
import UIKit
import ArticleKit
class PostArticleIntentHandler: NSObject, PostArticleIntentHandling {
func confirm(intent: PostArticleIntent,
completion: @escaping (PostArticleIntentResponse) -> Void) {
}
func handle(intent: PostArticleIntent,
completion: @escaping (PostArticleIntentResponse) -> Void) {
}
}
在这里,您将创建一个类来处理涉及您的发布article intent
的交互。
符合PostArticleIntentHandling
协议意味着您需要实现一个涉及确认步骤的方法和一个用户在确认后处理意图的方法。
接下来,添加以下代码到confirm(intent:completion:)
:
completion(PostArticleIntentResponse(code: PostArticleIntentResponseCode.ready,
userActivity: nil))
这表示如果用户点击确认,则扩展已准备好接受意图。
接下来,您将实现handle(intent:completion:)
。
这是真正的选择发挥作用的地方。 由于用户试图发布文章,因此只应在成功消息的情况下响应。
首先,在找不到他们选择的文章时添加此保护声明:
guard let title = intent.article?.identifier,
let article = ArticleManager.findArticle(with: title) else {
completion(PostArticleIntentResponse
.failure(failureReason: "Your article was not found."))
return
}
这会使用failure
意图响应调用completion
块。 它唯一的参数叫做failureReason
,因为你之前创建的失败响应模板在模板中有failReason
变量。
接下来,为本文已发布时添加一个guard
:
guard !article.published else {
completion(PostArticleIntentResponse
.failure(failureReason: "This article has already been published."))
return
}
最后,对于成功情况,您将发布文章并使用成功响应调用completion
块。 这包括文章的标题和发布日期:
ArticleManager.publish(article)
completion(PostArticleIntentResponse
.success(title: article.title, publishDate: article.formattedDate()))
现在您已经设置了intent
处理程序,您必须确保它已被使用。
打开IntentHandler.swift
并用以下内容替换现有的handler(for:)
,告诉系统使用刚写的处理程序:
override func handler(for intent: INIntent) -> Any {
return PostArticleIntentHandler()
}
接下来,打开AppDelegate.swift
并找到application(_:continue:restorationHandler:)
。
您可能没有想到的是,即使您有自己的处理程序来处理此快捷方式,仍会调用应用程序委托中的continue user activity callback
。
要阻止该方法将用户从Siri
中删除并进入new article view
,请添加以下guard
:
guard userActivity.interaction == nil else {
ArticleManager.loadArticles()
rootVC.viewWillAppear(false)
return false
}
如果活动附加了交互,则表示其为“publish”
快捷方式,您需要加载文章并确保重新加载feed view controller
。
构建并运行,然后编写新文章以提交其中一个快捷方式。
注意:您可以放心地忽略有关链接到
dylib
的警告,该dylib
在应用程序扩展中不安全。
接下来,进入Settings
并使用标题为其创建快捷方式;像“Post my last article”
有效的工作。
之后,启动Siri并使用您的快捷方式;Siri将为您发布该文章,并回复一个自定义回复,通知您标题和发布日期。
6. Wrapping Up
您需要担心的最后一件事是从系统中删除intents
。 假设用户删除了他们编写的唯一文章。 如果Siri提示他们发布这篇文章,那意味着系统会记住他们想要删除的信息。
由于这违反了Apple对用户隐私的严格尊重,因此删除已删除的活动和意图是您的职责。
转到ArticleFeedViewController.swift
并滚动到文件的底部。
然后,将以下方法调用添加到remove(article:indexPath:)
的底部:
INInteraction.delete(with: article.title) { _ in
}
completion
块允许您对您认为合适的删除错误做出反应。
由于新文章快捷方式不包含任何用户数据,因此不一定要删除它。
最后,打开Layouts.swift
并找到ArticleFeedViewController
的UITableViewDataSource
扩展。 在扩展名末尾添加以下内容以启用删除文章:
func tableView(_ tableView: UITableView,
commit editingStyle: UITableViewCell.EditingStyle,
forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let article = articles[indexPath.row]
remove(article: article, at: indexPath)
if articles.count == 0 {
NSUserActivity.deleteSavedUserActivities(withPersistentIdentifiers:
[NSUserActivityPersistentIdentifier(kNewArticleActivityType)]) {
print("Successfully deleted 'New Article' activity.")
}
}
}
}
如果需要,可以使用NSUserActivity
的类方法deleteSavedUserActivities(withPersistentIdentifiers:completionHandler :)
来删除使用单个标识符提交的所有活动。
如果您想了解有关Shortcuts
的更多信息,请查看2018年的两个WWDC视频。第一个first presentation涵盖了许多与本教程相同的材料,并且是一个很好的复习,以巩固您在这里学到的重要想法。 第二部分 second更多地涉及最佳实践。
后记
本篇主要介绍了构建Siri Shortcuts简单示例,感兴趣的给个赞或者关注~~~