iOS9之前普通的App应用只能够搜索应用名称,通过搜索到的应用来打开对应的应用。而其他的内容搜索功能只能够由苹果提供的系统应用使用,如邮件、短信等。iOS9提供的搜索三剑客为:
- NSUserActivity,从iOS8开始提供用于记录App状态,在iOS9及之后,不设计隐私内容,默认是可以被手机本地搜索
- CoreSpotlight,第三方app可以通过CSSearchableItem对象将待索引的用户内容持久化到本地,供本地搜索
- Web Markup,允许应用在其网站上做一些markup的标记,在spotlight中进行检索
本文着重介绍NSUserActivity的使用,NSUserActivity本来是为了支持Handoff使用的,在iOS9之后对其功能做了进一步提升。在使用NSUserActivity之前我们必须要了解Handoff的原理及一些使用场景,才能够更好的介绍NSUserActivity。
1、Handoff基本常识
Handoff是iOS8和OS X v10.10之后引入的一个新特性,即Continuity,让用户可以在不同设备之间进行信息互联互通。举个例子,当一个用户在Mac电脑上正在通过Safari浏览一篇很长的文章,此时他可以通过同一个iCloud帐号在iPhone、iPad上使用Safari继续浏览刚才的文章。借用一下苹果的图片,:)
Handoff的使用硬性条件:
- 需要做Handoff切换的设备必须都使用同一个iCloud帐号登录;
- 需要做切换的设备必须支持BlueTooth 4.0 LE;
- 需要做切换的设备必须处于联网状态,因为需要做数据数据同步;
- 需要做切换的设备,必须打开Handoff功能,这个可以在设置->通用->Handoff与建议的应用程序中打开。
备注:iPhone4s升级之后,并没有看到“Handoff与建议的应用程序”这个开关项,但是实际是默认已经开启了这个功能。其他比4s更高级的手机里面有这个选项。
2、NSUserActivity实现搜索功能
2.1 ActivityTypes指定
在工程的info.plist里面,增加NSUserActivityTypes项,如图(此处借用老外写的iOS 9 Search工程):
后面会使用这个唯一的com.tutsplus.iOS-9-Search.displayShow创建一个新的NSUserActivity对象
2.2 修改工程中的DetailViewController.swift文件
在修改工程文件之前,请先下载
工程文件。
- 修改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<span style="white-space:pre"> </span>
activity.eligibleForSearch = true
activity.eligibleForPublicIndexing = true
activity.needsSave = true //原工程中不存在此行
self.userActivity = activity<span style="white-space:pre"> </span>//原工程中不存在此行
self.userActivity.becomeCurrent()
}
}
eligibleForSearch = true和eligibleForHandoff = false,关闭Handoff切换功能和打开Search功能,表示此处仅用于CoreSpotlight搜索,而不进行应用间数据传递处理
eligibleForPublicIndexing = true,打开云索引功能,当很多用户都搜素时,所有安装过该应用的客户都能通过CoreSpotlight搜索到(即使用户没有打开过)
activity.needSave = true和self.userActivity = activity这两句是本人综合网上众多朋友写的文章里面的推测和提示,经过好几天的不停尝试得到的结果。缺少这两句根本就达不到前面提到的iOS 9 Search工程说明文章中老外描述的那个结果。
activity.needSave = true,表示需要存储当前的Activity
self.userActivity = activity,将新建立的Activity赋值给当前的controller对象
self.userActivity.becomeCurrent() ,用于激活当前Activity,回调updateUserActivityState方法,将新的Activity对象放到CoreSpotlight索引中
CocoaChina中的翻译版本地址为
iOS 9 学习系列:Search API
- 重载updateUserActivityState(activity: NSUserActivity)方法
override func updateUserActivityState(activity: NSUserActivity) {
super.updateUserActivityState(activity)
}
运行的效果图,可以参考前面给出两个链接文章中的图片,此处就不赘述了。