在wwdc 2015會議上,蘋果官方公布了ios9。除開許多新的特性和增強功能,這次更新也給了開發者們一個機會讓他們的app裡的内容能通過spotlight搜尋功能被發現和使用。在ios9中可用的新apis允許你去索引app裡面的内容或者界面狀态,通過spotlight來讓使用者使用。 這些新的搜尋apis的三大元件為:
nsuseractivity 類, 它是為可被看見的app内容而設計的
core spotlight 架構, 為任何app内容而設計的
web markup,為這一類型的app設計的,就是app的内容在某個網站上有鏡像
在這個教程裡,我将會向你展示可以怎樣在你的應用中使用nsuseractivity類以及 core spotlight 架構。
<a target="_blank"></a>
1.使用 nsuseractivity
在這個教程的開始部分,我将會給你展示怎樣通過nsuseractivity類來索引一個app裡的内容。這個api也是在handoff裡使用的那一個,handoff是在去年ios8中介紹的功能,它用于儲存和複原一個應用的目前狀态。
首先,打開工程然後到detailviewcontroller.swift檔案。把detailviewcontroller類裡configureview方法裡的内容替換為如下:
func configureview() {
// update the user interface for the detail item.
if self.namelabel != nil && self.detailitem != nil {
self.namelabel.text = detailitem.name
self.genrelabel.text = detailitem.genre
let dateformatter = nsdateformatter()
dateformatter.timestyle = .shortstyle
self.timelabel.text = dateformatter.stringfromdate(detailitem.time)
let activity = nsuseractivity(activitytype: "com.tutsplus.ios-9-search.displayshow")
activity.userinfo = ["name": detailitem.name, "genre": detailitem.genre, "time": detailitem.time]
activity.title = detailitem.name
var keywords = detailitem.name.componentsseparatedbystring(" ")
keywords.append(detailitem.genre)
activity.keywords = set(keywords)
activity.eligibleforhandoff = false
activity.eligibleforsearch = true
//activity.eligibleforpublicindexing = true
//activity.expirationdate = nsdate()
activity.becomecurrent()
}
}
在view controller裡,配置label的代碼是不變的,讓我們來一步一步分析 user activity 代碼:
使用唯一辨別符 com.tutsplus.ios-9-search.displayshow建立一個新的nsuseractivity對象。 這個工程已經被配置成確定使用這個辨別符時要保證它不會被改變。
然後為這個user activity 配置設定一個userinfo字典。它将會在後面被用來修複應用的狀态。
給activity的title屬性賦予了一個字元串值。這就是将會在spotlight 搜尋結果裡出現的内容。
為了確定可搜尋的内容不僅止限于應用的标題,你也要提供一系列的關鍵字。在上面的代碼段中,關鍵字清單中包含了每個節目的名字以及它的類型。
接下來,你向nsuseractivity對象賦予一些屬性來告訴作業系統你想讓這個user activity用來做什麼。在這個教程中,我們隻是檢視搜尋元件的api 是以我們把handoff禁用掉然後把search開啟。
最後, 調用user activity的becomecurrent方法,就在此時它自動的被加入到了裝置的搜尋結果索引中。
在以上的實作代碼中,你可能注意到了兩條被注釋的語句。盡管我們不會在這個教程中使用這些屬性,但是了解每個屬性是做什麼用的也是很重要的。
在上面的實作代碼中,每個節目的user activity和 搜尋結果都是僅當應用曾經被打開過時而建立的。當你讓你的user activity有eligibleforpublicindexing屬性時,apple就開始從使用者的搜尋結果當中觀察這個特殊activity的作用和互動了。如果這個搜尋結果是被很多使用者所使用的,apple就提升這個user activity到它自己的雲索引(cloud index)中。一旦這個user activity在這個雲索引中了,它就可以被所有安裝過你的應用的人搜尋得到,而不管他們是否有打開過那些内容。這個屬性隻有當且僅當activities能被你應用的所有使用者使用時才能被設定為true。
一個user activity 可以有一個可選的屬性expirationdate。 當這個屬性被設定時,你的user activity 隻會在設定的時期之前才會展示在搜尋結果裡。
現在你已經知道了怎樣建立一個可以在spotlight中展示搜尋結果的nsuseractivity,現在就來實驗吧。編譯運作你的app,然後在你的應用中打開一些節目。做完這些後,傳回到home頁面(在ios 模拟器中按 command-shift-h)然後向下掃或者滑動到最左邊的螢幕就可以拉起搜尋框視圖。
在搜尋框裡填入某個你已經打開了的節目的标題,你将會在搜尋結果裡看到它被顯示出來,如下圖。
另外的,輸入某個你已經打開了的節目的類别。歸功于你已經對user activity賦予了關鍵字資訊,這也會導緻節目将會在搜尋結果清單裡被列舉出來。
你應用的内容被作業系統正确的索引出來并且結果就展現在spotlight 裡。但是,當你輕觸一個搜尋結果時,你的應用并不會帶領使用者進入他們想要的搜尋結果裡面去,而隻是簡單地拉起這個應用。
幸運的是,通過 handoff, 你可以利用nsuseractivity類來複原應用裡的正确狀态。為了使這成為可能我們需要實作兩個方法。
如下所示在appdelegate類裡實作 application(_:continueuseractivity:restorationhandler:) 方法:
func application(application: uiapplication, continueuseractivity useractivity: nsuseractivity, restorationhandler: ([anyobject]?) -> void) -> bool {
let splitcontroller = self.window?.rootviewcontroller as! uisplitviewcontroller
let navigationcontroller = splitcontroller.viewcontrollers.first as! uinavigationcontroller
navigationcontroller.topviewcontroller?.restoreuseractivitystate(useractivity)
return true
接下來,在masterviewcontroller類裡實作restoreuseractivitystate方法:
override func restoreuseractivitystate(activity: nsuseractivity) {
if let name = activity.userinfo?["name"] as? string,
let genre = activity.userinfo?["genre"] as? string,
let time = activity.userinfo?["time"] as? nsdate {
let show = show(name: name, genre: genre, time: time)
self.showtorestore = show
self.performseguewithidentifier("showdetail", sender: self)
else {
let alert = uialertcontroller(title: "error", message: "error retrieving information from userinfo:\n\(activity.userinfo)", preferredstyle: .alert)
alert.addaction(uialertaction(title: "dismiss", style: .cancel, handler: nil))
self.presentviewcontroller(alert, animated: true, completion: nil)
在寫這篇文章的當下,xcode7(beta3)的最新版本有一個問題那就是一個用于修複的user activity的 userinfo 屬性會變成空。這就是為什麼我會處理errors以及展示一個userinfo(被作業系統傳回的)資訊的警告。
再次編譯運作你的app,搜尋一個節目。當你在搜尋結果裡輕觸一個節目時,app将會直接将你帶到詳細資訊的view controller并展示出你選擇的節目的目前資訊。
2.使用core spotlight 架構
另外一些在ios9中能使你的内容可被使用者搜尋得到的apis就是core spotlight 架構。這個架構有一個類似資料庫的設計并且能夠給你提供更多的關于你想被搜尋到的内容的資訊。
在你可以使用core spotlight架構之前,我們需要把這個工程同這個架構連結起來。在project navigator中,選中這個工程然後打開最上面的build phases欄目。接下來,展開 link binary with libraries 區域然後點選加号按鈕。在彈出的菜單中,搜尋 corespotlight 然後把你的工程跟這個架構連結起來。重複這些步奏來連結 mobilecoreservices 架構。
接下來,為了確定我們的app提供的搜尋的結果确實來自于core spotlight,在你的測試機或者模拟器上删除你的應用然後在detailviewcontroller類中注釋掉下面的這條語句:
activity.becomecurrent()
最後,打開masterviewcontroller.swift然後在show結構體定義之前添加下面的語句:
import corespotlight
import mobilecoreservices
接下來,在masterviewcontroller類的viewdidload方法裡添加下面的代碼:
var searchableitems: [cssearchableitem] = []
for show in objects {
let attributeset = cssearchableitemattributeset(itemcontenttype: kuttypeitem as string)
attributeset.title = show.name
let dateformatter = nsdateformatter()
dateformatter.timestyle = .shortstyle
attributeset.contentdescription = show.genre + "\n" + dateformatter.stringfromdate(show.time)
var keywords = show.name.componentsseparatedbystring(" ")
keywords.append(show.genre)
attributeset.keywords = keywords
let item = cssearchableitem(uniqueidentifier: show.name, domainidentifier: "tv-shows", attributeset: attributeset)
searchableitems.append(item)
cssearchableindex.defaultsearchableindex().indexsearchableitems(searchableitems) { (error) -> void in
if error != nil {
print(error?.localizeddescription)
// items were indexed successfully
在驗證這段代碼之前,我們先過一遍for循環裡的每一步。
你建立一個 cssearchableitemattributeset 對象, 給這個項目傳入一個内容類型(content type)。例如,如果你的搜尋結果連結到一張照片,那麼你就應該傳入kuttypeimage常量。
給屬性組合(attribute set)的title屬性賦予一個節目的名字。就如同 nsuseractivity一樣,這個标題就是将在搜尋結果清單的最頂端出現的那個。
接下來,建立一個描述性字元串然後把它指派給可搜尋的屬性組合(attribute set)的contentdescription屬性。這個字元串将會在spotlight中搜尋結果的标題下方出現。
就像在nsuseractivity當中建立的那樣,建立一個來自于搜尋結果的關鍵字數組。
最後,建立一個有着唯一項目辨別符的,唯一域辨別符(用來聚集cssearchableitem項目)的,和一個屬性組合(attribute set)的cssearchableitem,與nsuseractivity不同的是, nsuseractivity 從搜尋結果中傳回user activity, 當你的搜尋結果被使用者選中時,為cssearchableitem設定的所有唯一辨別符資訊就是你可以從作業系統那裡得到的唯一資訊。 你需要利用這些辨別符來複原你的應用回到正确狀态。
一旦你為每個tv節目建立了一個cssearchableitem項目時,你利用 indexsearchableitems(_:completionhandler:) 方法和預設的cssearchableindex對象來索引它們。
編譯運作你的app,你所有的節目将會被spotlight索引到。去到搜尋頁面然後搜尋其中一個節目。
core spotlight搜尋結果會被跟nsuseractivity裡一樣的那個方法所處理,但是過程有一些輕微差別。當一個cssearchableitem項目在搜尋結果裡被選中時,系統為你建立一個包含選中項目的唯一辨別符資訊的nsuseractivity對象。
在你的 app delegate的 application(_:continueuseractivity:restorationhandler:)方法中,可以利用下面的實作代碼從core spotlight 搜尋結果中擷取你要的資訊:
if useractivity.activitytype == cssearchableitemactiontype {
if let identifier = useractivity.userinfo?[cssearchableitemactivityidentifier] as? string {
// use identifier to display the correct content for this search result
return true
使用core spotlight架構來索引app内容的一個良好的實踐就是當項目不再被需要的時候删除它們。cssearchableindex類提供了三種方法來删除可搜尋項目:
deleteallsearchableitemswithcompletionhandler(:)
deletesearchableitemswithdomainidentifiers(:completionhandler:)
deletesearchableitemswithidentifiers(_:completionhandler:)
作為一個示例,添加下面代碼到masterviewcontroller類裡的viewdidload方法:
cssearchableindex.defaultsearchableindex().deletesearchableitemswithdomainidentifiers(["tv-shows"]) { (error) -> void in
// items were deleted successfully
再一次的編譯運作你的應用。當你想要搜尋任何節目時,不會有任何結果傳回回來,因為它們已經在索引當中被删除掉了。
3.聯合nsuseractivity和 core spotlight
另一個在ios9中nsuseractivity類的新增特性就是contentattributeset屬性。這個屬性允許你賦予一個cssearchableitemattributeset, 正如你先前建立的那個。這個屬性集合(attribute set)允許nsuseractivity對象的搜尋結果可以展示如同 core spotlight搜尋結果那樣的相同數量的詳細資訊。
首先向detailviewcontroller.swift中最頂部添加下面的imports:
接下來,用下面的實作代碼更新detailviewcontroller類的configureview方法:
let attributeset = cssearchableitemattributeset(itemcontenttype: kuttypeitem as string)
attributeset.title = detailitem.name
attributeset.contentdescription = detailitem.genre + "\n" + dateformatter.stringfromdate(detailitem.time)
最後一次編譯運作app,然後打開一些節目。當你搜尋一個節目時,你将會看到你的結果,伴随nsuseractivity的建立,擁有和core spotlight 搜尋結果相同級别的細節資訊。
總結
在這個教程中,你學習到了使用nsuseractivity類和 core spotlight架構來使你的應用裡的内容可被ios spotlight 索引。我也向你展示了怎樣使用這兩個apis在你的應用裡索引内容以及當一個搜尋結果被使用者選中時怎樣複原你的應用的狀态。
在ios9中介紹的新的搜尋apis使用都很友善而且可以使你的應用中的内容更簡單的被使用者發現和接觸。一如既往的,如果你有任何評論或問題,在下方的評論框裡留言。