在 iOS 9 之前,用户只能通过 Spotlight 搜索有限的基本内容,诸如备忘录、短信等,而从 iOS 9 开始,苹果允许用户搜索活动、App 状态、App 内容甚至未安装的 App 信息,也就是这篇博客要介绍的内容—— Search API。

关于其他 iOS 9 的特性与功能,有兴趣的朋友可以参考我博客中的 iOS 9 适配系列

我们所说的 Search API 共分为三种:

  • NSUserActivity

  • Web Markup

  • CoreSpotlight

本文主要介绍 CoreSpotlight 的基本使用(点击这里直接跳转),另外两种由于比较简单,因此只做基本概念阐述。

NSUserActivity

使用过 Handoff 功能的小伙伴们可能对 NSUserActivity 比较熟悉,因为这在 iOS 8 中专为 Handoff 推出的 API。

而在 iOS 9 中 NSUserActivity 的功能得到了显著提升,简单来说,从 iOS 9 开始用户只要在 Spotlight 中提供元数据(Metadata)即可搜索不同的 Activity(活动)。

Web Markup

Web Markup 是 iOS 9 新推出的功能,它用于在网页中显示 App 内容并编入 Spotlight 索引,也就是说即使用户并没有安装某个 App,iOS 9 也可以在网页上搜索特定标记(Markup)并在 Safari 或 Spotlight 中显示搜索结果。

如果你有兴趣你可以参考官方文档 Use Web Markup to Make App Content Searchable

CoreSpotlight

从名字就能看出 CoreSpotlight 是一套完整的 Spotlight 框架,它允许开发者将 App 中的任意内容编入索引使得这些内容可以在 Spotlight 相关搜索结果中显示,提供更好的用户体验。

NSUserDefault 不同,CoreSpotlight 使用系统的存储空间,它存储的内容称为 CSSearchableItem,我们可以通过 CSSearchableItemAttributeSet 为每个 CSSearchableItem 设置属性。

要使用 CoreSpotlight,首先需要引入 CoreSpotlight.framework (在 Target => Build Phases => Link Binary With Libraries 中添加)并导入头文件:

import CoreSpotlight

接下来创建 CSSearchableItemAttributeSetCSSearchableItem:

let identi = "meniny"

let attrSet = CSSearchableItemAttributeSet(itemContentType: "someType")
attrSet.title = identi
attrSet.contentDescription = "Some Description Here"
attrSet.thumbnailData = UIImageJPEGRepresentation(UIImage(named: "icon_Image")!, 0.5)

let item = CSSearchableItem(uniqueIdentifier: identi, domainIdentifier: "cn.meniny.MXSearchAPIDemo", attributeSet: attrSet)

调用 CSSearchableIndex.defaultSearchableIndex()indexSearchableItems(items: [CSSearchableItem], completionHandler: ((NSError?) -> Void)?) 方法将内容编入索引:

CSSearchableIndex.defaultSearchableIndex().indexSearchableItems([item], completionHandler: { (error) -> Void in
	if error == nil {
		print("saved")
	}
})

最后,当用户点击搜索结果后,系统会自动跳转到我们的应用,因此我们需要在 AppDelegateapplication(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool 方法编写跳转后的相关逻辑:

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
   let identifier = userActivity.userInfo?["kCSSearchableItemActivityIdentifier"] as? String

   let nav = window?.rootViewController as! UINavigationController
   nav.popToRootViewControllerAnimated(false)

   let newVC = UIViewController()
   newVC.title = identifier
   newVC.view.backgroundColor = UIColor.whiteColor()

   nav.pushViewController(newVC, animated: true)

   return true
}

此外,CoreSpotlight 还提供了三种删除索引的方法,分别是:

  • deleteSearchableItemsWithIdentifiers(identifiers: [String], completionHandler: ((NSError?) -> Void)?),根据 identifiers: [String] 删除

  • deleteSearchableItemsWithDomainIdentifiers(domainIdentifiers: [String], completionHandler: ((NSError?) -> Void)?),根据 domainIdentifiers: [String] 删除

  • deleteAllSearchableItemsWithCompletionHandler(completionHandler: ((NSError?) -> Void)?),删除全部

这三种方法通过单例 CSSearchableIndex.defaultSearchableIndex() 调用即可,十分简单不做赘述。