如何使用iOS 9的Core Spotlight框架

發表於2016-02-02

iOS每一次版本的更新,都會給全球的開發工作者帶來新的“知識點”和對現有技術進行的改進。顯然,iOS的最新版本iOS 9不僅延續了這一傳統,還公佈了新的框架和API,開發者可使用新增的框架和API讓自己的應用表現的更出色。其中之一就是Core Spotlight框架,它包含了一些優秀的API,有待開發者深入探究。

Core Spotlight (CS) 框架是Search API的一部分,它增加了開發者的應用的曝光率,使使用者更容易發現和訪問APP,但是這些API在iOS9之前的版本中是不可用的。這些Search API拉近了使用者和app的距離,使用者可以通過這種新的方法迅速的找到app,而app也可以迅速的對使用者的操作做出反應。除了Core Spotlight之外,iOS 9還包含以下新的search功能(僅供參考):

1、NSUserActivity這個類中新的方法和屬性(該類負責儲存app關閉時的狀態,以便之後恢復app的狀態。)

2、在裝置上使用web標記,以便搜尋到web中的內容。

3、能通過web內容中的連結直接啟動應用程式的通用連結。

本文不會對以上三點做詳細介紹,只詳細講解Core Spotlight框架。在講解之前,先了解以下Core Spotlight到底是什麼?

32.png

如上圖所示:Core Spotling框架可以讓使用者通過Spotlight搜尋到app中的資料,並將app相關內容和系統搜尋返回的結果一起展示出來。也就是說使用者可以與應用程式的其他相關結果進行互動,當點選其中一項搜尋結果時並不僅僅自動啟動APP,開發者也可以讓使用者選擇與資料最相關的內容。

從開發者的角度來說,整合Core Spotlight框架並使用它提供的API並不是一件難事。學過這教程之後,你將會發現僅僅需要幾行程式碼就可以實現這個功能。整合的核心問題在於開發者必須把APP的資料以特定的格式加入到iOS系統的索引中。

由於本教程專注於Core Spotlight框架的使用,所以我不打算深入研究這個框架。

關於Demo App

和往常一樣,我們打算通過一個示例應用來研究探索Spotlight的細節。在這個demo中,我們將往應用程式中寫入一組資料,並且這些資料都是可以通過真機或模擬器的Spotlight功能被搜尋到的。雖然實現Spotlight功能搜尋是重點,但是還是有必要介紹一下關於demo app 的更多細節。

我們的示例應用要達到的效果是展示一些電影及其相關的資訊,例如電影概要、導演、明星以及影評等級等。所有的電影資料將會放在列表中展示,並且當點選到對應的行時,所選擇的電影會在一個新的檢視控制器中展示出電影的詳情。這些功能和資料作為我們挖掘Spotlight的API而言已經夠用了。我們的資料來源是International Movie Database (IMDB),我們從這個網站獲得資料示例。

通過看下面的動畫示例,你可以先看一下演示程式的效果:

t46_1_app_working-compressor.gif

在本教程中,我們有兩個目的:最重要的是讓這個應用內的所有電影方面的資料都可以被Spotlight搜尋到。當使用者通過關鍵字搜尋時,應用程式內關於電影的資料將會展現給使用者。設定這些關鍵字是我們接下來工作的一部分,我們必須重新定義它們,使之符合規則。

點選搜尋結果會開啟應用程式,之後我們要實現第二個目標。如果我們沒有做任何的處理,那麼將會載入包含有電影資料列表的預設檢視控制器展示給使用者。然而,假如我們考慮到使用者體驗的話,這麼處理並不是很好。好的方案是,我們的APP應該展示Spotlight選中的電影的詳情。簡言之,我們不僅要讓應用程式內的電影資料能夠通過Spotlight被搜尋到,而且還要在使用者點選搜尋結果時,展示關聯的電影詳情頁。接下來的示例動畫會講解的更清楚:

t46_2_final_sample-compressor.gif

為了節約時間,你可以在這裡下載工程,然後開始我們的工作。在工程裡面你會發現如下所示的內容:

  • 介面部分的元件已經搭建完成,並且包含所有必要的IBOutlet屬性。
  • 最小化的列表檢視。
  • 所有的電影資料都存放在以plist為字尾的檔案中。此外圖片檔案是和電影一一對應的(一共有5部)。

假使你想知道預先準備的檔案中包含了哪些對應電影的資料,那麼你可以通過這個截圖示例看到所有包含的內容。

t46_3_movie_plist_sample.png

先看一下Core Spotlight API的具體資訊,我們會處理下面兩個任務:

1、在列表中載入和展示電影資料。

2、在選中電影資料列表的某一行時會跳轉到對應的電影詳情介面。

啟動專案沒有實現上邊的內容,儘管那樣麼做會讓你們快速進到我們的話題,原因很簡單:我很確信通過演示應用程式的核心功能和資料樣本,你會很容易地瞭解到將要被Spotlight搜尋到的具體資料。但是別擔心,因為所有準備工作花費的時間很少,並且很快就可完成。

載入和展示示例資料

假如此時你已經下載好了起始工程,並且已經看過了電影資料屬性列表,那麼就讓我們開始Coding吧。在MoviesData.plist這個資料夾下,你可以看到一共有5條資料,這些資料是從IMDB網站上隨機選取的他們對應5個電影示例。我們第一步是從plist檔案中載入資料到一個陣列中,然後在列表中展示他們。

廢話少說,直接上程式碼。開啟ViewController.swift這個檔案,並且在這個類宣告屬性的地方這麼寫:

所有的電影模型資料都會被載入到moviesInfo可變陣列中,單個電影模型的資料將會以鍵值對的方式儲存在字典中,並且他們和檔案中的屬性列表相匹配。

現在讓我們編寫一個載入資料的自定義函式。接下來你會看到,我們只是確保屬性列表檔案是否存在,如果存在,我們就初始化陣列的檔案內容:

接下來我們需要在viewDidLoad()函式呼叫loadMoviesInfo()函式。只是為了確保你在呼叫configureTableView()函式前正確呼叫此函式,下面展示的是程式碼片段:

要注意的是,我們只需把檔案內容載入到viewDidLoad()函式,而不是為了建立上述的loadMoviesInfo()函式,但是作為喜歡程式碼整潔的人,即便是這麼小的事情,都會選擇更好的方式來實現。

應用程式每次啟動時都會載入這些電影資料,我們可以繼續修改當前檢視列表,讓它顯示電影資訊。需要處理的只有這麼多:根據電影資料資訊定義列表的行數,然後在表檢視的單元格中展示正確的電影資料。

從列表檢視的行數開始,顯然列表檢視的行數等於電影的數目。然而,我們不應忘記,要確保列表檢視中有電影資料展示出來,否則當檔案內容不被載入到陣列中時就會造成應用程式的崩潰。

最後,讓我們展示電影資料。為了達到我們需要的目標,在開始準備的工程中你可以找到UITableViewCell的子類MovieSummaryCell,和代表一個電影單元格的.xib檔案:

33.png

用這樣的一個單元格來展示每個電影的圖片、標題、部分的描述資訊和電影評級。所有UI控制元件已經連線到IBOutlet屬性,並且可以在MovieSummaryCell.swift這個檔案找到對應屬性的名稱:

上面的名字代表各個屬性的用途,現在我們已經能夠看到它們,我們通過它們來展示電影的相關細節。回到ViewController.swift檔案,根據下面的程式碼片段更新表檢視的函式:

雖然currentMovieInfo這個字典不是必需的,但是它讓上面的簡單程式碼編寫的更加容易。

這時你可以執行一次你的應用程式,並且可以看到電影的細節被展示在表檢視。到目前為止,我們所做的這些是大家所熟知的,所以直接到第二個步驟:顯示所選電影的細節。

資料細節展示

在MovieDetailsViewController這個類中,我們將要展示在ViewController類中tableView上選中的電影的細節。所有的介面構建已經完成,現在我們必須做兩件事:把包含電影資訊的字典從ViewController類傳到MovieDetailsViewController類中,然後從字典取值賦值給這個類中相應的UI控制元件,這些控制元件的IBOutlet屬性都已經被宣告並且已經正確的連線到單個UI元件上。

所以,說到字典,讓我們在MovieDetailsViewController類中做下面的宣告:

回到ViewController.swift檔案,讓我們看一下點選表檢視的行時需要做的工作有哪些。當點選列表的一行時,我們需要知道點選行的索引,以便於從moviesInfo陣列選擇合適的字典,然後在檢視跳轉的時候把字典傳遞到下一個檢視控制器。從tableview的委託方法中獲取行索引是很容易的,但是我們需要一個自定義的屬性來儲存它,因此在ViewController類的頂部我們需要這麼宣告:

然後,我們需要用下面的方式處理tableView中選中row的索引:

有兩個簡單的事情需要處理:第一是把點選的行的索引儲存在我們自定義的selectedMovieIndex屬性中,然後執行跳轉到展示電影詳情的介面。然而,這是不夠的,因為我們還未從moviesInfo陣列中選擇相應的包含電影資訊的字典,並把它傳遞到MovieDetailsViewController這個類中。我們該怎麼做呢?重寫prepareForSegue:sender:函式,並實現我剛剛描述的功能。下面是程式碼,請看:

很簡單,我們只通過destinationViewController的segue屬性獲得MovieDetailsViewController例項,然後我們將包含電影資訊的字典值賦給我們這部分開始時宣告的movieInfo屬性。

現在,再次開啟MovieDetailsViewController.swift檔案,我們將會在這裡定義一個自定義的函式。在它裡面,我們將會從movieInfo字典中取值賦給那些相應的控制元件,那麼這部分的工作到這裡就就結束了。下面的程式碼是一個簡單的實現,所以不再做進一步的探討:

最後,在viewWillAppear:中函式呼叫上面的函式,程式碼如下

這一部分已經結束。再執行一下你的應用程式,一旦你選中tableView中的某一個電影機就會看到電影的詳細介紹。

為Spotlight新增app的索引資料

通過使用iOS9中提供的Core Spotlight 框架,使得任何一款應用都可以通過Spotlight功能被搜尋到。在Spotlight上通過使用者的搜尋行為找到app的關鍵在於使用Core Spotlight API索引到我們應用的資料。但是既不是我們的app也是不是CS API介面決定應該設定什麼型別的資料。所以我們需要提供特定的資料格式給 API介面。

再具體點來說,就是我們想通過Spotlight功能搜尋到得資料必須封裝成CSSearchableItem型別的物件,然後一起組裝到陣列中並把這個陣列傳遞給CS API 中供它索引。單個的CSSearchableItem物件包含一系列的屬性,這些屬性使得iOS系統可搜尋物件的細節更加清楚。像在搜尋時應該展示哪些資料片段(例如:電影名稱、圖片和影視簡介等),哪些app的資料關鍵字需要在Spotlight上展示。CSSearchableItemAttributeSet 類物件為 CSSearchableItem物件提了許多屬性,只需為我們所需要的屬性賦值就好了。檢視官方文件,你可以找到所有支援的屬性。

最後一步通常要做的是為Spotlight功能新增索引資料。一般情況下,實現流程如下步驟所示(包含新增索引):

1、給每一條資料設定屬性,例如電影模型資料(設定CSSearchableItemAttributeSet物件)。

2、使用上一步的屬性值(CSSearchableItem物件),為每一條資料初始化搜尋項並賦值。

3、收集所有的可搜尋項放到一個陣列中。

4、使用上個步驟的陣列作為Spotlight的索引資料。

我們將按照上面的步驟一個一個的實現,為了達到目標,我們將會在ViewController.swift這個檔案內建立一個叫做setupSearchableContent()的函式。在這部分功能實現結束之際,你會發現實現讓你的資料可以被搜尋到的功能一點也不難。不過,我不會一次性給你所有的實現程式碼;相反,為了你更容易理解,我打算把程式碼分為片段。別擔心,程式碼量並不是那麼多。

在我們開始實現新功能之前,我們必須先匯入兩個框架:

我們定義一個新的方法,同時在方法中宣告一個用來存放我們蒐集到的搜尋項的陣列:

現在在一個for迴圈中訪問每一個包含電影資訊的字典:

我們將為每一部電影建立一個CSSearchableItemAttributeSet物件,然後我們將為搜尋項資料設定屬性,這些搜尋項資料將會在使用者使用Spotlight搜尋時作為搜尋結果展示出來。在demo App中,我們將把電影的標題、簡介和圖片作為資料展示給使用者。

注意上面的片段程式碼中我們是如何設定電影資料模型中圖片屬性的。有兩種實現方法:一種是為imge制定一個URL連結,另一種是為image提供一個NSData物件。最簡單的方法是為每一個電影圖片檔案提供一個URL,因為我們知道它們就在程式應用包裡面。然而,這樣做就需要我們把每個圖片檔名分割成實際名稱和擴充套件型別,因此我們用String類的 componentsSeparatedByString:方法將這兩個值分開。剩下的程式碼就容易理解了。

現在是時候為app在Spotlight上設定我們想要的data的關鍵字了。指定關鍵字之前要認真考慮,因為你的決定對使用者和App在Spotlight上的曝光率起著最終的決定性作用。在demo App中我們把電影所屬的類別和演員設定成關鍵字。

記住,電影的所有類別屬性在MoviesData.plist檔案中是用一個字串值來表示的,並且它們被逗號隔開。所以很有必要把這個字串分割出各種電影的種類使他們成為各個單獨的值,然後把他們存入movieCategories陣列中以方便及時訪問。然後用一個for迴圈在keywords陣列中新增分類的關鍵字。對電影資料模型的明星屬性使用相同的步驟,也就是說我們再次把包好所有明星名字的字串分割成單獨的值,然後把他們存入keywords陣列中。

上面的片段程式碼中最後一句程式碼是很重要的,我們為每一個電影資料模型設定了關鍵字屬性。忘記了這一點,當用Spotlight搜尋時將不會出現任何關於我們app的結果。

我們已經為Spotlight設定了屬性和關鍵字,那麼現在是時候初始化搜尋項,並且把它們新增到searchableItems陣列中,程式碼如下:

上述searchableItem物件的初始化接受了三個引數:

  • uniqueIdentifier:這個引數唯一地標識Spotlight當前搜尋項。你可以用你喜歡的方式構造這個唯一標示符,但是注意一個細節:在這個例子中,我們為當前電影新增了索引標示符,因為之後我們需要用它來匹配索引相對應得電影細節展示介面。一般而言,在唯一識別符號的值裡面新增詳情頁要展示的資料是個好主意。一會你將會更好的理解電影資料模型的索引值的用途。
  • domainIdentifier:使用這個引數對搜尋項進行分組。
  • attributeSet:它就是我們剛剛設定屬性時的屬性設定物件。

在最後,把新的搜尋項新增到searchableItems陣列中。

還有最後一步需要做,用Core Spotlight的API去索引這些搜尋項。它發生在for迴圈之外地方:

上面的函式已經完成,但是我們需要呼叫它。我們將會在viewDidLoad()函式中呼叫它:

現在我們準備第一次開始用Spotlight搜尋電影。執行app,然後退出app使用Spotlight搜尋上面我們設定的關鍵字。結果將會展現到你眼前,通過點選搜尋結果中的任意項,這個app將自動啟動。

36.gif

實現目標

當用Spotlight搜尋時,能夠從應用程式中搜尋到電影資料是會給人深刻的印象,但是我們還可以比這做的更好。現在,當選擇一個搜尋結果時,就會啟動應用程式,並且展示出ViewController這個介面,但是我們目標是直接進到展示電影細節介面並可以直接看到所選擇電影的資訊。

儘管這聽起來比較困難,或者難以實現,但是最終你會發現它很簡單。在這個指定的demo app中,根據我們現有的資料展示所選電影項的詳細資訊會更簡單。

這裡主要的工作是重寫UIKit中的一個名字叫做restoreUserActivityState:的函式,並處理Spotlight上選中的結果項。我們最終的目標是從搜尋項的識別符號(如果你還記得話,我們在上一個部分動態的建立了識別符號)中提取出在moviesInfoarray陣列中的電影模型的索引值,然後用它傳遞一個正確的電影資料字典並展示MovieDetailsViewController檢視。

restoreUserActivityState:函式的引數是NSUserActivity物件。這個物件有一個字典型別的屬性名為userInfo,這個字典包含Spotlight上選中搜尋項的識別符號。從這個識別符號中我們可以提取出moviesInfo陣列中電影資料模型的索引值,然後我們就可以展示電影詳情頁面的檢視了。就這麼多,下面看一下程式碼實現:

如你所見,有必要先檢查activity type是否和CSSearchableItemActionType匹配。老實說,在示例程式中這個並不重要,但是如果你在你的應用程式中處理多個NSUserActivity物件的情況下,有些事是不應該忘記的做的(例如,Handoff feature是ios8首次提出來的,並且它充分使用了NSUserActivityclass類)。在useInfo字典中identifer物件是一個字串。一旦我們得到它,我們將基於點符號擷取這個字串,我們從擷取的字串陣列中取出最後一個物件就是選中的電影資料模型在電影資料模型陣列中的索引值。剩下的就工作就比較簡單:將這個索引值複製給selectedMovieIndex屬性,然後執行跳轉。我們之前的實現將會完成剩餘的工作。

現在切換到AppDelegate.swift檔案。我們需要實現一個現在還未實現的代理函式。每次點選在Spotlight上搜尋的一個結果時,那個函式就會呼叫一次,我們現在的任務是呼叫我們上面已經實現的函式,傳遞userActivity物件,請看下面的實現程式碼:

在上面的程式碼片段中,我們要做的第一件事就是通過window屬性訪問ViewController檢視控制器,以恢復到之前的使用者活動狀態。或者,不用上面的方法,你可以用NSNotificationCenter類傳送一個自定義的通知,然後在ViewController 類中處理這個通知,但上面的方法更直接。

就這麼多!我們的示例應用已經完成了,所以再次執行它,看看你在使用Spotlight搜尋電影時會發生什麼。

37.gif

總結

iOS 9 中新的搜尋API對開發者來說看起來相當的吸引人,它們使得使用者更容易發現和訪問APP。在這個教程中我們實現了所有Spotlight搜尋App資料的相關操作,包括方便使用者在Spotlight上搜尋時App資料索引,以及如何把選中的結果項通過app處理後的資料展示給使用者。在你的應用程式實現這樣的功能肯定會提升使用者體驗,所以你應該在你當前和未來的專案認真考慮使用它。又到了結束的時候,我真希望你能發現這篇文章的有用之處!

作為參考,你從GitHub上可以下載完整的工程。

相關文章