在iOS 10中创建SiriKit扩展

最终产品图片
您将要创造的

介绍

自2011年推出Siri以来,iOS开发人员一直在寻求将第三方应用与其集成的可能性。 随着WWDC 2016期间iOS 10的发布,Apple终于向开发人员提供了SiriKit。 哪些类型的应用程序可以利用Siri仍然存在一些限制,但这是朝着正确方向迈出的一步。 让我们来看看Siri可以做什么。

支援网域

要使用SiriKit,您的应用必须位于以下一个或多个域中:

  • VoIP通话(例如,Skype)
  • 消息传递(WhatsApp)
  • 付款(平方,贝宝)
  • 照片(照片)
  • 锻炼(Runtastic)
  • 乘车预订(Uber,Lyft)
  • CarPlay(仅限汽车供​​应商)
  • 餐厅预订(需要Apple的额外支持)

如果您的应用不属于上述任何类别,那么很遗憾,您目前无法在应用中使用Siri。 不过,请不要离开,因为SiriKit非常强大,并且将来可能会获得新功能!

扩展架构

实际上,SiriKit扩展由两种类型的扩展组成。 Intents扩展程序是必需的,它负责处理用户的请求并在您的应用程序中执行特定任务(例如,启动呼叫,发送消息等)。

另一方面, IntentsUI扩展不是必需的。 仅当您要自定义Siri在显示数据时显示的用户界面时,才应创建一个。 如果您不这样做,则将显示标准Siri界面。 在本教程中,我们将介绍两种扩展类型。

供您参考,Apple在WWDC 2016期间发布了两个非常有趣的有关SiriKit的视频。 您可能需要检查一下它们:

示例项目

我们将构建一个简单的应用程序,通过Siri处理付款。 目标是成功处理句子“通过TutsplusPayments向Patrick寄出20美元”。 句子的格式包括具有特定货币的金额,收款人的姓名以及用于完成交易的应用程序。 稍后我们将更详细地分析付款意图。

最初设定

让我们首先在Swift中创建一个标准的Xcode项目并为其命名。 在编写任何代码以使您的应用程序可以使用Siri的API之前,您必须执行一些强制性步骤。

1. 选择焦油 GET>功能 ,并启用Siri的能力。 确保在您的项目结构中成功创建了权利。

Xcode项目功能视图

2.打开应用程序的Info.plist并添加密钥NSSiriUsageDescription 。 该值必须是一个说明您对Siri用法的字符串,当要求初始许可时,该字符串将显示给用户。

3.选择文件>新建>目标 。 在Xcode呈现的新窗口中的“ 应用程序扩展”下 ,选择“ 意图扩展” 。 还选择包含UI扩展的选项。 这样可以避免以后创建另一个单独的扩展名。

新的Intent扩展目标

在新创建的Intents目标的Info.plist文件中,完全展开NSExtension词典以研究其内容。 该词典更详细地描述了扩展支持的意图,以及是否要允许用户在设备锁定时调用意图。

如果要支持多个目的,请在顶部插入最相关的意图。 Siri使用此顺序来找出用户要使用的模棱两可的情况。

现在,我们需要定义我们要支持的意图。 在此示例中,我们将构建一个支持付款意图的扩展。 修改Info.plist文件以匹配下图。

意图信息plist文件

在这里,我们指定我们要处理INSendPaymentIntent并要求设备解锁。 我们不希望陌生人在设备丢失或被盗时发送付款!

iOS目标

下一步实际上涉及在iOS应用中编写一些代码。 我们必须征求用户的许可才能将其声音发送给Apple进行分析。 我们只需要导入Intents框架并调用适当的方法,如下所示:

import UIKit
import Intents 

class ViewController: UIViewController {

    override func viewDidLoad() {
 	    super.viewDidLoad()
		// Ask permission to access Siri
		INPreferences.requestSiriAuthorization { authorizationStatus in
			switch authorizationStatus {
			case .authorized:
				 print("Authorized")
			default:
				print("Not Authorized")
			}
		}
	}
}

在应用程序首次启动期间向用户显示的结果对话框将如下所示。

要求获得访问Siri权限的警报

这就是我们在简单的iOS应用中所要做的全部。 让我们现在进入扩展世界!

意图扩展

切换到我们之前创建的Intents扩展。 在Xcode项目导航器中展开其内容。 您只会看到一个名为IntentHandler.swift文件。

该文件是扩展程序的入口,用于处理Siri发送给您的所有意图。 如果您的扩展支持多种类型,Siri会将所有意图转发给handler(for:)方法。 检查INIntent对象的类型并适当地处理它是您的工作。

IntentHandler.swift模板已经包含Messaging目的的示例实现。 用以下空方法替换所有代码,以便我们可以逐步完成每个步骤。

class IntentHandler: INExtension {
     
    override func handler(for intent: INIntent) -> Any? {
        // This is the default implementation.  If you want different objects to handle different intents,
        // you can override this and return the handler you want for that particular intent.         
        return self
    }
}

每个意图都有一个相关的协议,以确保一个类实现所有必需的方法。 Intents框架中的大多数协议都具有相同的结构。

我们将要实现的协议称为INSendPaymentIntentHandling 。 该协议包含以下必需和可选方法:

  • 需要:
    handle(sendPayment:completion:)
  • 可选的:
    confirm(sendPayment:completion:)
    resolvePayee(forSendPayment:with:)
    resolveCurrencyAmount(forSendPayment:with:)
    resolveNote(forSendPayment:with:)

让我们在同一Swift文件中创建IntentHandler类的扩展,以实现唯一所需的方法。

extension IntentHandler: INSendPaymentIntentHandling {
 
    func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
        // Check that we have valid values for payee and currencyAmount
 	    guard let payee = intent.payee, let amount = intent.currencyAmount else {
            return completion(INSendPaymentIntentResponse(code: .unspecified, userActivity: nil))
        }
 	    // Make your payment!
 	    print("Sending \(amount) payment to \(payee)!")
        completion(INSendPaymentIntentResponse(code: .success, userActivity: nil))
    }
}

这是一个非常基本的实现。 我们确保有有效的payeecurrencyAmount将交易设置为成功。 您可能不相信它,但是它已经起作用了! 从Xcode中选择Intents方案并运行它。 当Xcode显示通常的菜单以选择要运行的应用程序时,请选择Siri。

在Xcodes菜单中运行扩展

当Siri启动时,尝试说“通过TutsplusPayments将20美元发送给Patrick”。 现在,享受您用语音完成的首次成功付款!

通过Siri首次成功付款

您也可以尝试测试失败的情况。 尝试说与以前相同的句子,但不指定收款人(即:“通过TutsplusPayments发送$ 20”)。 您会看到Siri失败,并向用户显示一个按钮以继续在您的应用程序中付款。

由于缺少收款人姓名,付款失败

如果Siri无法理解或未提供其中一个可选参数,但您需要一个有效值,则可以实现resolve方法之一。 这些方法为用户提供了一个选项,以提供有关付款的更多详细信息,例如收款人姓名,确切的货币金额,甚至是便条。 借助此API的智能体系结构,您作为开发人员可以轻松而清晰地以不同方式理解用户的请求。

在真实世界的应用程序中,您将创建一个动态框架,该动态框架将在您的iOS应用程序和扩展之间共享。 通过使用此体系结构,您可以在多个目标中共享相同的业务逻辑。 您无需多次实施它,而只需一次实现所有目标!

意图UI扩展

在本教程的最后一部分,我将向您展示如何自定义Siri显示的用户界面。

首先,请记住要像在上一节中所做的那样,在ExtensionUIInfo.plist中设置要处理的正确的意图类。

跳到Intents UI扩展,您将看到Xcode为您创建的模板。 它包含一个IntentViewController ,它是实现INUIHostedViewControlling协议的UIViewController的简单子类。 还为您创建了一个情节提要文件。 打开它,以便我们可以开始自定义用户界面。

添加一个UIImageView作为背景,并在中心添加一个标签。 下载背景图像 ,将其导入Intents UI目标,并将其设置为新创建的UIImageView的图像。 创建一个UILabel对象,并将其放置在视图的中心。 您可以轻松使用AutoLayout在Storyboard中设置约束。

打开助手编辑器,为标签创建一个@IBOutlet ,并将其@IBOutletcontentLabel 。 结果应如下所示:

演示图板显示了新的IntentsUI视图

打开IntentViewController文件,您将看到很多示例代码。 您可以删除除我们现在要实现的configure(with:context:completion:)方法之外的所有内容。 当准备好配置用户界面时,将调用此方法。 我们要做的是设置UILabel的内容。

class IntentViewController: UIViewController, INUIHostedViewControlling {
     
    @IBOutlet weak var contentLabel: UILabel!
     
    // MARK: - INUIHostedViewControlling
 
    func configure(with interaction: INInteraction!, context: INUIHostedViewContext, completion: ((CGSize) -> Void)!) {
 
        if let paymentIntent = interaction.intent as? INSendPaymentIntent {
            // If any of this properties is not set, use the default UI.
            guard let amount = paymentIntent.currencyAmount?.amount, let currency = paymentIntent.currencyAmount?.currencyCode, let name = paymentIntent.payee?.displayName else {
                return completion(CGSize.zero)
            }
            let paymentDescription = "\(amount)\(currency) to \(name)"
            contentLabel.text = paymentDescription
        }
        if let completion = completion {
            completion(self.desiredSize)
        }
    }
     
    var desiredSize: CGSize {
        return self.extensionContext!.hostedViewMaximumAllowedSize
    }
}

首先,我们检查intent对象是否为INSendPaymentIntent类型。 如果是的话,我们还要确保要显示的所有属性都不为nil ,否则我们只需调用大小为零的完成块来隐藏我们的自定义视图。 如果一切都按预期进行,我们将使用要显示给用户的数据创建一个自定义字符串,并将其设置为contentLabel的文本。

再次运行扩展程序,您将在Siri中看到新视图!

Siri扩展中的新自定义UI

Siri仍显示默认视图。 我们可以通过使我们的视图控制器符合INUIHostedViewSiriProviding协议来隐藏它。

class IntentViewController: UIViewController, INUIHostedViewControlling, INUIHostedViewSiriProviding {
    // Previous code goes here...
    var displaysPaymentTransaction: Bool {
        return true
    }
}

通过在displaysPaymentTransaction变量中返回true ,我们告诉Siri我们的视图控制器正在照顾向用户显示所有必要的信息,并且可以隐藏默认视图。 结果现在更加干净!

Siri显示的自定义UI的最终结果

注意:如您在这张照片中看到的,当指定不同于美元的货币时,Siri会正确理解货币代码并将其返回给扩展程序。 不幸的是,文本始终显示美元。 我已将此错误报告给Apple!

结论

希望您喜欢本教程。 即使当前仅限于某些类型的应用程序,Siri也非常强大。 如果您打算在自己的应用程序中实现它,请确保将其很好地推销给您的用户,因为他们可能不知道您的应用程序变得多么酷炫和先进!

翻译自: https://code.tutsplus.com/tutorials/create-sirikit-extensions-in-ios-10--cms-27924

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值