更聪明的搜索 Spotlight

人们已经越来越离不开搜索,搜索最大的目的其实就是让人在短时间内得到想要的东西,简单的说就是提升效率。

使用App也是在提升效率,淘宝、京东提升购物效率,微信、陌陌提升射交效率,猎聘、拉钩提升招聘效率...

iOS中的Spotlight已经不新鲜了,个人使用习惯的不同可能让有些人不知道她的存在,在手机存储暴增的今天,手机里不装个几百个App可能有点对不住你128G的存储了,但如果还滑来滑去的找应用那就说不过去了,在最新的iOS9中,Spotlight的功能肯定不止应用搜索这么简单。

简单的计算:


计算器

货币转换:

货币转换

以前可能还需要你打开App才能做到的,现在只需要简单几步就搞定,可能还有一些小惊喜等着你去发掘,如果你还有其他的好玩的,记得告诉我。

iOS 9 中的Spotlight还能搜索包括第三应用程序提供的app内信息,让用户搜索到的信息更可靠、更丰富、更人性化、更具联动性,并且允许开发者设置任意内容让Spotlight索引到。
我们能做些什么?
你不需要打开App 就能快速定位到想要找到的内容。
而且可以把更多的快捷操作放入搜索中。

  • 输入好友名字立即打开聊天窗口;
  • 输入歌名立即播放;
  • 输入患者信息进入至患者详情;
  • 输入cpatient(create patient)立即进入创建患者页面;
  • ...

Apple也给了一些应用场景

新的API

在iOS 9 中提供了三种API来帮助我们实现搜索:

NSUserActivity

NSUserActivity 从iOS 8开始就已经在Handoff中使用了,可以通过activity 中传输的数据在另一台设备上继续。

Handoff

文档也说的很详细,本文主要讲搜索,就不对Handoff做过多说明。
在iOS 9中 NSUserActivity提供了一些新的方法和属性来帮助我们索引到指定的某个导航页面来继续操作,可以是新建或者查看列表内容等等。

Core Spotlight

新的Core Spotlight框架允许所有应用程序中的任何内容添加索引,来用Spotlight方便访问,当然你也可以对索引进行添加、删除、更新。使用Core Spotlight可以索引到应用程序中的内容,即使应用程序没有运行。

Using a search extension, you can index content in the background even if your app is not running. This allows you to keep the index up to date as content changes even if the user isn't actively using your app. This is great for things like messages and conversations stored on your server but accessed through your app, or for locally generated user content.

Web Markup

这个特性就是你如果在你的网站上打上了Apple规范的markup内容,Applebot爬虫就会爬你的网站,然后出现在Spotlight 和Safari的搜索结果中。也就是说用户不用安装你的应用,你的应用也有机会展示给潜在用户。

写几行代码吧

接下来要做的是让应用可以在Spotlight中根据更多的关键字搜索到。

搜索

先看看搜索结果是如何展示的。


import Foundation
import CoreSpotlight
import MobileCoreServices

@available(iOS 9.0, *)
class SpotlightManager: NSObject {

    class func setupOpenAppAction() {
        var searchableItems: [CSSearchableItem] = []

        let openAppSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
        openAppSet.title = "MedClipper"
        openAppSet.keywords = ["patient", "diagnosis", "doctor", "病历夹"]
        let openAppSetItem = CSSearchableItem(uniqueIdentifier: "openApp", domainIdentifier: nil, attributeSet: openAppSet)
        searchableItems.append(openAppSetItem)

        CSSearchableIndex.defaultSearchableIndex().indexSearchableItems(searchableItems, completionHandler: { (error) -> Void in
            if let error = error {
                print("SearchableIndex error: \(error.localizedDescription)")
            }
        })
    }
}

我加入了"patient", "diagnosis", "doctor", "病历夹" 关键字,通过这些关键字都能搜索出App,在应用启动之后调用setupOpenAppAction,退出应用就可以搜索了。
然后我们只需要在Spotlight中输入定义好的关键字,你的App就会出现在搜索结果中了。

doctor

当然,除了这种方式,你还可以给你的App起一个很长的名字或者副标题。

QQ音乐

你除了可以通过QQ音乐搜索到之外,还能通过听歌、K歌、FM、电台等关键字搜索到QQ音乐。

小众音乐

通过我们、音乐、倾听、彼此都能在Spotlight中搜索到小众音乐。

这样的命名方式无论是Spotlight 还是 App store 都可以让你的App在用户面前有更多的展示机会。

搜索结果处理

接下来我们来处理搜索结果,点击之后的跳转,让用户可以通过搜索结果跳转到创建页面,或者是详情页面。

我们需要再定义一个用来执行创建操作的CSSearchableItem和多个可以被搜索用来查看详情的CSSearchableItem

import Foundation
import CoreSpotlight
import MobileCoreServices

@available(iOS 9.0, *)
class SpotlightManager: NSObject {
    class func setupOpenAppAction() {
        var searchableItems: [CSSearchableItem] = []

        let openAppSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
        openAppSet.title = "MedClipper"
        openAppSet.keywords = ["patient", "diagnosis", "doctor", "病历夹"]
        let openAppSetItem = CSSearchableItem(uniqueIdentifier: "openApp", domainIdentifier: nil, attributeSet: openAppSet)
        searchableItems.append(openAppSetItem)

        let createPatientSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
        createPatientSet.title = "Create Patient Info"
        createPatientSet.contentDescription = "创建患者信息"
        createPatientSet.keywords = ["cp", "create patient", "patient", "sick", "create patient", "cs"]
        let createPatientItem = CSSearchableItem(uniqueIdentifier: "create-Patient", domainIdentifier:nil, attributeSet:createPatientSet)
        searchableItems.append(createPatientItem)
        CSSearchableIndex.defaultSearchableIndex().indexSearchableItems(searchableItems, completionHandler: { (error) -> Void in
            if let error = error {
                print("SearchableIndex error: \(error.localizedDescription)")
            }
        })
    }

    class func setupUserData() {
        CSSearchableIndex.defaultSearchableIndex().deleteSearchableItemsWithDomainIdentifiers(["patient"]) { (error) -> Void in
            if let error = error {
                print("SearchableIndex delete error: \(error.localizedDescription)")
            } else {
                var searchableItems: [CSSearchableItem] = []
                let patients = Patient.findAll()
                for (index, patient) in patients.enumerate() {
                    let patientSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
                    patientSet.title = "\(patient.firstName) \(patient.lastName)"
                    patientSet.contentDescription = patient.medicalHistory
                    patientSet.keywords = [patient.firstName, patient.lastName]
                    let patientItem = CSSearchableItem(uniqueIdentifier: "patient-\(index)", domainIdentifier:"patient", attributeSet:patientSet)
                    searchableItems.append(patientItem)
                }
                CSSearchableIndex.defaultSearchableIndex().indexSearchableItems(searchableItems, completionHandler: { (error) -> Void in
                    if let error = error {
                        print("SearchableIndex error: \(error.localizedDescription)")
                    }
                })

            }
        }
    }
}

setupOpenAppAction() 定义快捷打开方式的索引。
setupUserData() 定义可搜索的数据索引。
由于用户在App中会对数据进行修改新增,所以把setupUserData()在用户按Home退出之后再更新数据索引。

func applicationDidEnterBackground(application: UIApplication) {
    if #available(iOS 9.0, *) {
        SpotlightManager.setupUserData()
    }
}

然后通过代理方法来处理用户点击搜索结果之后的回调,如果不做处理默认只会打开App。

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
    if #available(iOS 9.0, *) {
        if userActivity.activityType == CSSearchableItemActionType {
            guard let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String else {
                return true
            }
            if identifier == "create-Patient" {
                //跳转到新建的页面
            } else if identifier.hasPrefix("patient-") {
                let patientId = identifier.substringFromIndex(identifier.startIndex.advancedBy(8))
                //通过patientId 跳转到详情页面
            }
        }
    }
    return true
}

我们通过userInfo中的identifier来确定用户的动作来执行下一步操作
好的,完成了,我们来看下效果:

Activity Result

是的,就是这么简单,让搜索变得更聪明。

据说聪明的人都懂得用搜索。

参考:
App Search Programming Guide

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容