iOS 9 App Search Tutorial: Introduction to App Search
Apple开放了可以让Spotlight和siri能够搜索app内容的接口。iOS 9支持应用内搜索,用户可以使用系统的Spotlight来搜索应用内的东西。
App search APIs
-
NSUserActivity: 在ios8中
NSUserActivity
已经被用作handoff了。iOS 9 中添加了一些属性,如果一个程序把一个任务从这个设备handoff到另一个设备。那么这个任务就可以在这个设备的Spotlight中被搜索到。 - Core Spotlight:为任何APP内容而设计的
- Web markup :为这一类型的APP设计的,就是APP的内容在某个网站上有镜像
接下来主要介绍的是NSUserActivity
NSUserActivity
实现一个应用搜索,NSUserActivity
是首先需要解决的,因为:
- 当用
NSUserActivity
标记用户的活动,iOS会将内容分级,这样搜索结果就会按一定等级存取内容了 - 这样只差一步就可以支持Handoff
实现NSUserActivity
导入
import CoreSpotlight
声明一个反转DNS格式的字符串:例如
public static let domainIdentifier = "com.baidu"
-
设置
NSUserActivity
实例的属性public var userActivity: NSUserActivity { let activity = NSUserActivity(activityType: domainIdentifier) activity.title = name activity.userInfo = userActivityUserInfo activity.keywords = [email, department] //需要被呈现的属性,如下定义 activity.contentAttributeSet = attributeSet return activity } //CSSearchableItemAttributeSet 呈现的是一系列的需要被展现的搜索属性 public var attributeSet: CSSearchableItemAttributeSet { let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeContact as String) attributeSet.title = name attributeSet.contentDescription = "\(department), \(title)\n\(phone)" attributeSet.thumbnailData = UIImageJPEGRepresentation( loadPicture(), 0.9) // 需要导入import MobileCoreServices attributeSet.supportsPhoneCall = true attributeSet.phoneNumbers = [phone] attributeSet.emailAddresses = [email] attributeSet.keywords = skills return attributeSet }
-
最后重载
override updateUserActivityState()
. 这步保证当一个搜索结果被选中,你会有得到需要的信息//这里添加了搜索的内容是userActivityUserInfo的值 override func updateUserActivityState(activity: NSUserActivity) { activity.addUserInfoEntriesFromDictionary(userActivityUserInfo) }
上述代码只能保证 ,在Spotlight中打开该打开搜索内容的app ,但是不进入app所对应的内容,在appdelegate中
application(_:continueUserActivity:restorationHandler:)
,当用户点击搜索结果会调用这个方法,通过userActivity.activityType来判断是那个应用程序,并打开这个app,然后通过所点击的内容打开相应地app
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
guard userActivity.activityType == domainIdentifier,
let objectId = userActivity.userInfo?["id"] as? String else {
return false
}
//这个是相应的内容
if let nav = window?.rootViewController as? UINavigationController,
listVC = nav.viewControllers.first as? EmployeeListViewController,
employee = EmployeeService().employeeWithObjectId(objectId) {
nav.popToRootViewControllerAnimated(false)
let employeeViewController = listVC
.storyboard?
.instantiateViewControllerWithIdentifier("EmployeeView") as!
EmployeeViewController
employeeViewController.employee = employee
nav.pushViewController(employeeViewController, animated: false)
return true
}
return false
}
-
删除内容 ,需要导入
import CoreSpotlight
,根据需要有
deleteSearchableItemsWithDomainIdentifiers(_:completionHandler:)
删除整个identifiers区域的搜索
deleteSearchableItemsWithIdentifiers(_:completionHandler:)
删除单个记录
deleteAllSearchableItemsWithCompletionHandler(_:completionHandler:)
删除所有搜索public func destroyEmployeeIndexing() { CSSearchableIndex .defaultSearchableIndex() .deleteAllSearchableItemsWithCompletionHandler { error in if let error = error { print("Error deleting searching employee items: \(error)") } else { print("Employees indexing deleted.") } } }