SiriKit框架詳細(xì)解析(八) —— 構(gòu)建Siri Shortcuts簡(jiǎn)單示例(二)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.12.06 星期四

前言

大家都知道隨著人工智能的發(fā)展纹份,會(huì)掀起來另外一個(gè)工業(yè)革命,而語(yǔ)音識(shí)別就是人工智能的初始階段棱貌,但是每個(gè)公司做的都不一樣锣披,涉及到一系列的語(yǔ)音的采集和算法實(shí)現(xiàn)原环,蘋果的Siri就是業(yè)界語(yǔ)音識(shí)別的代表性的產(chǎn)品挠唆。接下來的幾篇我們就詳細(xì)解析一下SiriKit這個(gè)框架。感興趣的可以看下面幾篇文章嘱吗。
1. SiriKit框架詳細(xì)解析(一)—— 基本概覽(一)
2. SiriKit框架詳細(xì)解析(二)—— 請(qǐng)求授權(quán)使用SiriKit和INPreferences類(一)
3. SiriKit框架詳細(xì)解析(三)—— 創(chuàng)建Intents App擴(kuò)展(一)
4. SiriKit框架詳細(xì)解析(四)—— 構(gòu)建代碼以支持App擴(kuò)展和將意圖調(diào)度到處理對(duì)象(一)
5. SiriKit框架詳細(xì)解析(五) —— 編程指南之Intents和Intents UI擴(kuò)展(一)
6. SiriKit框架詳細(xì)解析(六) —— 編程指南之確認(rèn)和處理請(qǐng)求玄组、指定自定義詞匯表和界面(一)
7. SiriKit框架詳細(xì)解析(七) —— 構(gòu)建Siri Shortcuts簡(jiǎn)單示例(一)

Publishing Articles with Siri

接下來,您希望添加發(fā)布直接從Siri編寫的文章的功能谒麦。 這里的最大區(qū)別在于俄讹,不是Siri打開你的應(yīng)用程序,一切都將直接來自Siri UI绕德。

對(duì)于此快捷方式患膛,您將創(chuàng)建一個(gè)自定義Intent來定義Siri,您的用戶和您的應(yīng)用之間的來回耻蛇。

1. Defining a Custom Writing Intent

在項(xiàng)目導(dǎo)航器中踪蹬,找到ArticleKit文件夾并單擊它以突出顯示它。

然后臣咖,按Command + N創(chuàng)建一個(gè)新文件跃捣。

在過濾器搜索框中,鍵入Intent夺蛇,您將看到SiriKit Intent Definition File疚漆。

單擊Next,然后將文件命名為ArticleIntents.intentdefinition刁赦。

現(xiàn)在是時(shí)候創(chuàng)建一個(gè)發(fā)布你寫的文章的intent了娶聘。

轉(zhuǎn)到讀取No Intents的部分的底部,然后單擊加號(hào)按鈕以添加新的intent意圖甚脉。

將其命名為PostArticle丸升,然后根據(jù)這些設(shè)置配置您的意圖(在圖片后面描述):

此屏幕用于配置發(fā)布intent需要處理的信息。

Custom Intent部分中的選項(xiàng)定義了它的意圖類型宦焦,并且可以影響Siri如何處理該操作发钝。 告訴Siri這是一個(gè)Post類型動(dòng)作讓系統(tǒng)知道你在某處分享了一些內(nèi)容:

  • 1) CategoryPost
  • 2) TitlePost Article
  • 3) DescriptionPost 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部分用于定義TitleSubtitle中使用的任何動(dòng)態(tài)屬性,您現(xiàn)在可以使用這些屬性波闹。

定義一個(gè)名為article的參數(shù)酝豪,它是一個(gè)Custom數(shù)據(jù)類型,一個(gè)是類型為StringpublishDate精堕。

然后孵淘,在Shortcut Types部分中,單擊加號(hào)按鈕以添加一個(gè)包含articlepublishDate參數(shù)作為其參數(shù)的類型歹篓。

接下來瘫证,設(shè)置快捷方式的TitleSubtitle

將標(biāo)題設(shè)置為Post “${article}”和副標(biāo)題設(shè)置為on ${publishDate}庄撮。 如果您不復(fù)制和粘貼背捌,請(qǐng)確保讓Xcode自動(dòng)完成articlepublishDate

最后洞斯,確保選中Supports background execution毡庆,這樣您就不會(huì)被迫離開Siri UI

2. Setting Up Siri’s Responses

單擊Response烙如,您可以定義Siri將如何響應(yīng)用戶么抗。

再次,配置您的響應(yīng)亚铁,如下所示:

Properties下蝇刀,您可以再次定義Siri所說的動(dòng)態(tài)部分。 添加title徘溢,publishDatefailureReason的屬性吞琐;把它們都定義為字符串。

然后然爆,在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

為了能夠在不啟動(dòng)應(yīng)用程序的情況下繼續(xù)使用Siri的UI,您需要使用可以管理交互的代碼創(chuàng)建Intents Extension施蜜。

單擊左上角的項(xiàng)目文件卒蘸,然后找到允許您添加新目標(biāo)的加號(hào)。

現(xiàn)在翻默,找到Intents Extension目標(biāo)缸沃;您可以在過濾搜索欄中搜索它。

然后修械,將您的意圖擴(kuò)展名為WritingIntents趾牧,將Starting Point設(shè)置為None,并取消選中Include UI Extension選項(xiàng)肯污。

最后翘单,單擊Finish按鈕以創(chuàng)建擴(kuò)展吨枉。 構(gòu)建并運(yùn)行以確保事情仍然有效。

注意:當(dāng)Xcode提供激活WritingIntents方案時(shí)哄芜,單擊Cancel貌亭。

沒什么新鮮的,但現(xiàn)在你已經(jīng)準(zhǔn)備好使用你的custom intents了认臊!

在繼續(xù)之前圃庭,您需要做兩件快速的事情。

首先失晴,確保擴(kuò)展名中可以看到ArticleIntents.intentdefinition剧腻。

打開文件,然后查看File inspector涂屁。 確保其Target Membership包括應(yīng)用程序书在,框架和擴(kuò)展。 此外拆又,請(qǐng)確保將應(yīng)用程序和擴(kuò)展目標(biāo)的代碼生成選項(xiàng)更改為No Generated Classes蕊温,因?yàn)榇舜a應(yīng)存在于框架中。

接下來遏乔,您的擴(kuò)展程序和主應(yīng)用程序需要共享一個(gè)應(yīng)用程序組义矛。 由于文章保存到磁盤并從磁盤加載,因此這是兩個(gè)目標(biāo)在文件系統(tǒng)上共享同一區(qū)域的唯一方法盟萨。

單擊Project導(dǎo)航器中的項(xiàng)目文件凉翻,確保選擇了TheBurgeoningWriter并轉(zhuǎn)到Capabilities選項(xiàng)卡。

App Groups功能切換為ON捻激,并命名組為group.<your-bundle-id>制轰。

接下來,選擇WritingIntents擴(kuò)展并執(zhí)行相同的操作胞谭。 這一次垃杖,該組應(yīng)該存在,因此您可以只檢查該框丈屹。

最后调俘,打開ArticleManager.swift并找到groupIdentifier的聲明。 更改其值以匹配新定義的應(yīng)用程序組名稱旺垒。

注意:此更改后彩库,您輸入的先前文章將不再顯示在應(yīng)用中。 這是預(yù)期的先蒋,因?yàn)樗鼈兇鎯?chǔ)在文件系統(tǒng)中的不同位置骇钦。

4. Donating Post Article Intents

現(xiàn)在您已經(jīng)定義了發(fā)布文章的intent,現(xiàn)在是時(shí)候在適當(dāng)?shù)臅r(shí)候創(chuàng)建和提交一個(gè)竞漾。

再一次眯搭,前往Article.swift窥翩,這樣你就可以添加一種方法來為新文章生成“post”intents

newArticleShortcut(thumbnail :)的定義下方鳞仙,添加以下方法定義:

public func donatePublishIntent() {

}

此方法一次創(chuàng)建并提供intent寇蚊,因?yàn)槟恍枰幚硐蛞晥D控制器添加intents

現(xiàn)在繁扎,創(chuàng)建intent對(duì)象并分配article and publish date

let intent = PostArticleIntent()
intent.article = INObject(identifier: self.title, display: self.title)
intent.publishDate = formattedDate()

當(dāng)使用自定義intent時(shí)幔荒,您最終提交給系統(tǒng)的事情就是這樣的交互糊闽。

最后梳玫,通過在交互上調(diào)用donate(_ :)來提交:

interaction.donate(completion: nil)

在這里,您將提交您的互動(dòng)右犹,而不必?fù)?dān)心completion塊提澎。 當(dāng)然,您可以將錯(cuò)誤處理或其他任何內(nèi)容添加到此完成塊中念链。

您必須完成最后一次“secret handshake”步驟:您必須告訴iOS確切的應(yīng)用程序支持的intents盼忌。 為此,請(qǐng)單擊Project導(dǎo)航器中的項(xiàng)目文件掂墓。 選擇WritingIntents目標(biāo)谦纱,然后單擊Info選項(xiàng)卡。 按住Option鍵并單擊NSExtension鍵旁邊的顯示三角形以打開整個(gè)鍵君编。 將鼠標(biāo)懸停在IntentsSupported上以顯示加號(hào)按鈕并單擊一次跨嘉。 將新添加的項(xiàng)的值設(shè)置為PostArticleIntent

這就是向系統(tǒng)提交intent-based的快捷方式的全部?jī)?nèi)容吃嘿。

現(xiàn)在您已經(jīng)定義了方法祠乃,轉(zhuǎn)到NewArticleViewController.swift并找到saveWasTapped()。 由于您希望系統(tǒng)提示用戶發(fā)布他們以后保存的文章兑燥,因此您可以在這里實(shí)現(xiàn)亮瓷。

添加此行以在該方法中的注釋下方提交intent

article.donatePublishIntent()

現(xiàn)在您正在提交,構(gòu)建和運(yùn)行應(yīng)用程序降瞳。 然后嘱支,創(chuàng)建并保存新文章。 完成后挣饥,轉(zhuǎn)到Spotlight搜索斗塘,您應(yīng)該會(huì)看到一個(gè)類似于此的新提交。

5. Handling Intents-Based Shortcuts

像以前一樣亮靴,您現(xiàn)在必須考慮在用戶使用它時(shí)處理此快捷方式馍盟。

這一次,您創(chuàng)建的擴(kuò)展將負(fù)責(zé)處理事物茧吊。

首先贞岭,在名為PostArticleIntentHandler.swiftWritingIntents文件夾中添加一個(gè)新的Swift文件八毯。

用以下內(nèi)容替換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) {

  }
}

在這里,您將創(chuàng)建一個(gè)類來處理涉及您的發(fā)布article intent的交互瞄桨。

符合PostArticleIntentHandling協(xié)議意味著您需要實(shí)現(xiàn)一個(gè)涉及確認(rèn)步驟的方法和一個(gè)用戶在確認(rèn)后處理意圖的方法话速。

接下來,添加以下代碼到confirm(intent:completion:)

completion(PostArticleIntentResponse(code: PostArticleIntentResponseCode.ready,
                                     userActivity: nil))

這表示如果用戶點(diǎn)擊確認(rèn)芯侥,則擴(kuò)展已準(zhǔn)備好接受意圖泊交。

接下來,您將實(shí)現(xiàn)handle(intent:completion:)柱查。

這是真正的選擇發(fā)揮作用的地方廓俭。 由于用戶試圖發(fā)布文章,因此只應(yīng)在成功消息的情況下響應(yīng)唉工。

首先研乒,在找不到他們選擇的文章時(shí)添加此保護(hù)聲明:

guard let title = intent.article?.identifier,
    let article = ArticleManager.findArticle(with: title) else {
        completion(PostArticleIntentResponse
          .failure(failureReason: "Your article was not found."))
        return
}

這會(huì)使用failure意圖響應(yīng)調(diào)用completion塊。 它唯一的參數(shù)叫做failureReason淋硝,因?yàn)槟阒皠?chuàng)建的失敗響應(yīng)模板在模板中有failReason變量雹熬。

接下來,為本文已發(fā)布時(shí)添加一個(gè)guard

guard !article.published else {
    completion(PostArticleIntentResponse
      .failure(failureReason: "This article has already been published."))
    return
}

最后谣膳,對(duì)于成功情況竿报,您將發(fā)布文章并使用成功響應(yīng)調(diào)用completion塊。 這包括文章的標(biāo)題和發(fā)布日期:

ArticleManager.publish(article)
completion(PostArticleIntentResponse
  .success(title: article.title, publishDate: article.formattedDate()))

現(xiàn)在您已經(jīng)設(shè)置了intent處理程序继谚,您必須確保它已被使用烈菌。

打開IntentHandler.swift并用以下內(nèi)容替換現(xiàn)有的handler(for:),告訴系統(tǒng)使用剛寫的處理程序:

override func handler(for intent: INIntent) -> Any {
  return PostArticleIntentHandler()
}

接下來犬庇,打開AppDelegate.swift并找到application(_:continue:restorationHandler:)僧界。

您可能沒有想到的是,即使您有自己的處理程序來處理此快捷方式臭挽,仍會(huì)調(diào)用應(yīng)用程序委托中的continue user activity callback捂襟。

要阻止該方法將用戶從Siri中刪除并進(jìn)入new article view,請(qǐng)?zhí)砑右韵?code>guard:

guard userActivity.interaction == nil else  {
    ArticleManager.loadArticles()
    rootVC.viewWillAppear(false)

    return false
}

如果活動(dòng)附加了交互欢峰,則表示其為“publish”快捷方式葬荷,您需要加載文章并確保重新加載feed view controller

構(gòu)建并運(yùn)行纽帖,然后編寫新文章以提交其中一個(gè)快捷方式宠漩。

注意:您可以放心地忽略有關(guān)鏈接到dylib的警告,該dylib在應(yīng)用程序擴(kuò)展中不安全懊直。

接下來扒吁,進(jìn)入Settings并使用標(biāo)題為其創(chuàng)建快捷方式;像“Post my last article”有效的工作室囊。

之后雕崩,啟動(dòng)Siri并使用您的快捷方式魁索;Siri將為您發(fā)布該文章,并回復(fù)一個(gè)自定義回復(fù)盼铁,通知您標(biāo)題和發(fā)布日期粗蔚。

6. Wrapping Up

您需要擔(dān)心的最后一件事是從系統(tǒng)中刪除intents。 假設(shè)用戶刪除了他們編寫的唯一文章饶火。 如果Siri提示他們發(fā)布這篇文章鹏控,那意味著系統(tǒng)會(huì)記住他們想要?jiǎng)h除的信息。

由于這違反了Apple對(duì)用戶隱私的嚴(yán)格尊重肤寝,因此刪除已刪除的活動(dòng)和意圖是您的職責(zé)当辐。

轉(zhuǎn)到ArticleFeedViewController.swift并滾動(dòng)到文件的底部。

然后醒陆,將以下方法調(diào)用添加到remove(article:indexPath:)的底部:

INInteraction.delete(with: article.title) { _ in
}

completion塊允許您對(duì)您認(rèn)為合適的刪除錯(cuò)誤做出反應(yīng)瀑构。

由于新文章快捷方式不包含任何用戶數(shù)據(jù)裆针,因此不一定要?jiǎng)h除它刨摩。

最后,打開Layouts.swift并找到ArticleFeedViewControllerUITableViewDataSource擴(kuò)展世吨。 在擴(kuò)展名末尾添加以下內(nèi)容以啟用刪除文章:

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 :)來刪除使用單個(gè)標(biāo)識(shí)符提交的所有活動(dòng)。

如果您想了解有關(guān)Shortcuts的更多信息耘婚,請(qǐng)查看2018年的兩個(gè)WWDC視頻罢浇。第一個(gè)first presentation涵蓋了許多與本教程相同的材料,并且是一個(gè)很好的復(fù)習(xí)沐祷,以鞏固您在這里學(xué)到的重要想法嚷闭。 第二部分 second更多地涉及最佳實(shí)踐。

后記

本篇主要介紹了構(gòu)建Siri Shortcuts簡(jiǎn)單示例赖临,感興趣的給個(gè)贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胞锰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兢榨,更是在濱河造成了極大的恐慌嗅榕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吵聪,死亡現(xiàn)場(chǎng)離奇詭異凌那,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吟逝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門帽蝶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人块攒,你說我怎么就攤上這事励稳〗鹂常” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵麦锯,是天一觀的道長(zhǎng)恕稠。 經(jīng)常有香客問我,道長(zhǎng)扶欣,這世上最難降的妖魔是什么鹅巍? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮料祠,結(jié)果婚禮上骆捧,老公的妹妹穿的比我還像新娘。我一直安慰自己髓绽,他們只是感情好敛苇,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顺呕,像睡著了一般枫攀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上株茶,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天来涨,我揣著相機(jī)與錄音,去河邊找鬼启盛。 笑死蹦掐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僵闯。 我是一名探鬼主播卧抗,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鳖粟!你這毒婦竟也來了社裆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤牺弹,失蹤者是張志新(化名)和其女友劉穎浦马,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體张漂,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晶默,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了航攒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磺陡。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出币他,到底是詐尸還是另有隱情坞靶,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布蝴悉,位于F島的核電站彰阴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拍冠。R本人自食惡果不足惜尿这,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望庆杜。 院中可真熱鬧射众,春花似錦、人聲如沸晃财。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)断盛。三九已至罗洗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郑临,已是汗流浹背栖博。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工屑宠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厢洞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓典奉,卻偏偏與公主長(zhǎng)得像躺翻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卫玖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容