Swift - CoreSpotlight框架的使用(实现应用内的数据搜索)
过去 Spotlight 功能有限,我们只能通过搜索应用名称来打开指定 App,或者搜索系统应用中的内容(如信息,联系人,邮件等)。对于我们 App 中的内容搜索,Spotlight 就无能为力了。

(2)程序运行后退出,然后使用 Spotlight 搜索结果如下:

(2)根据 domain(分组范围)删除索引
(3)根据 ID 删除索引
当用户点击搜索结果时会自动打开这个应用,并调用 AppDelegate 中的 continue userActivity 方法。我们可以在该方法中获取点击项的索引 ID,从而进行后续操作,比如:打开相应的页面或执行相关操作。
自在 iOS9 起,苹果放开了权限。允许开发者将应用中任意内容设置成可以被 Spotlight 索引到,以及用户在选择了搜索内容时会发生什么。比如我在系统 Spotlight 搜索框中输入“iPhone7”,可以看到 UC 中的内容被搜索出来了。

一、Core Spotlight介绍
1,基本概念
- Core Spotlight 框架是 iOS9 提供的一组新的 API,用来帮助我们建立起我们应用中内容的索引,并实现指向应用内的深层链接。
- Core Spotlight 创建的索引存储在设备上,不与 Apple 共享,也不能被其他应用或者设备访问。
- Core Spotlight 创建的索引最好在几千的数量级别之下。索引太多很有可能会带来性能问题。
2,建立索引的相关类
- CSSearchableItemAttributeSet:索引属性集合,也即是索引的内容本身。集合中可以存储以下属性:title、contentDescription、thumbnailData、rating、keywords。下图显示 Spotlight 是如何通过这些属性展示搜索结果的。(如果未设置缩略图则默认显示应用图标)
- CSSearchableItem:用来表示一个被索引的条目。其在构建的时候需要传入一个 CSSearchableItemAttributeSet 对象。
二、Core Spotlight使用样例
1,索引的创建
(1)下面代码实现当程序启动后,自动新增5条索引记录。import UIKit
import CoreSpotlight
import MobileCoreServices
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//判断设备支持情况
guard CSSearchableIndex.isIndexingAvailable() else {
print("该设备不支持添加Spotlight搜索!")
return
}
//创建索引集合
var items = [CSSearchableItem]()
for i in 1..<7 {
//创建索引属性
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData
as String)
attributeSet.title = "hangge.com 系列文章\(i)"
attributeSet.contentDescription = "这个是一段简单的描述"
attributeSet.keywords = ["article\(i)", "swift"]
attributeSet.thumbnailData = UIImagePNGRepresentation(UIImage(named: "a")!)
//创建索引项
let item = CSSearchableItem(uniqueIdentifier: "\(i)",
domainIdentifier: "group1", attributeSet: attributeSet)
items.append(item)
}
//保存新增的索引
let sIndex = CSSearchableIndex.default()
sIndex.indexSearchableItems(items, completionHandler: { (error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("索引添加成功!")
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

2,索引的删除
(1)删除全部索引let sIndex = CSSearchableIndex.default()
sIndex.deleteAllSearchableItems(completionHandler: { (error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("删除成功!")
}
})
(2)根据 domain(分组范围)删除索引
let sIndex = CSSearchableIndex.default()
sIndex.deleteSearchableItems(withDomainIdentifiers: ["group1"], completionHandler: {
(error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("删除成功!")
}
})
(3)根据 ID 删除索引
let sIndex = CSSearchableIndex.default()
sIndex.deleteSearchableItems(withIdentifiers: ["1","2"], completionHandler: { (error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("删除成功!")
}
})
3,搜索结果的点击响应
当用户点击搜索结果时会自动打开这个应用,并调用 AppDelegate 中的 continue userActivity 方法。我们可以在该方法中获取点击项的索引 ID,从而进行后续操作,比如:打开相应的页面或执行相关操作。
import UIKit
import CoreSpotlight
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
if userActivity.activityType == CSSearchableItemActionType {
let uniqueIdentifier = userActivity
.userInfo?[CSSearchableItemActivityIdentifier] as? String
print("点击的索引ID为:\(uniqueIdentifier)")
//执行后续操作.....
}
return true
}
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)
-> Bool {
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
}

嗯,我知道从continue useractivity 那个方法中继续写,但我不知道该怎么写了。因为正常的那些页面都还没有出现,UITabVC>UINavigationVC>UICollectionVC>UIVC,我就是不知道该怎么写,不知道该怎么展示,能给我说下思路吗? 是要取到各个VC然后怎么串起来呢
另外:苹果邮件收到的回复信,里面文字是乱码,好像是邮件文字编码的问题。
哇,看这个学会了 SpotLight,但有个问题搞不懂, 在点选 SpotLIght item 的时候,如何在自己的应用中呈现那个详情页呢。
我的应用结构是 UITabVC UINavigationVC UICollectionVC UIVC, 我需要把他们从头到尾串一遍吗? 如果显示呢?
赞