简介在WWDC2015大会上,Apple正式发布了iOS9。除了许多新功能和增强功能外,此更新还为开发人员提供了一个机会,使他们的应用程序中的内容可以通过Spotlight搜索发现和使用。iOS9中可用的新API允许您索引应用程序中的内容或界面状态,并通过Spotlight将其提供给用户。这些新的搜索API的三个主要组件是:NSUserActivity类,这是为可见应用程序内容设计的CoreSpotlight框架,以及为任何应用程序内容设计的网络标记,为此类应用程序设计,是应用程序的内容在网站上有镜像。在本教程中,我将向您展示如何在您的应用程序中使用NSUserActivity类和CoreSpotlight框架。准备工作本教程要求您运行Xcode7和OSX10.10或更高版本。为了跟上我的步伐,你还需要在GitHub上下载初始项目。1.使用NSUserActivity在本教程的开头,我将向您展示如何通过NSUserActivity类对APP的内容进行索引。这个API也是Handoff中使用的API。Handoff是去年iOS8引入的功能。它用于保存和恢复应用程序的当前状态。如果你以前没有使用过NSUserActivity,那么我建议你在开始本教程之前阅读我的这篇教程,它涵盖了Handoff和NSUserActivity的基础知识。在开始写代码之前,先打开初始项目,然后在iOS模拟器或测试机上运行APP。在此阶段,您会看到该应用仅显示4个电视节目的列表,以及每个节目的详细页面。首先,打开项目并转到DetailViewController.swift文件。将DetailViewController类中的configureView方法中的内容替换为以下内容:[“名称”:detailItem.name,“genre”:detailItem.genre,“time”:detailItem.time]activity.title=detailItem.namevarkeywords=detailItem.name.componentsSeparatedByString(“”)keywords.append(detailItem.genre)活动.keywords=Set(keywords)activity.eligibleForHandoff=falseactivity.eligibleForSearch=true//activity.eligibleForPublicIndexing=true//activity.expirationDate=NSDate()activity.becomeCurrent()}}在视图控制器中,配置标签??的代码保持不变,让我们来分析一下循序渐进ty代码:使用唯一标识符com.tutsplus.iOS-9-Search.displayShow创建一个新的NSUserActivity对象,该项目已经配置保证使用这个标识符保证不可更改。然后为这个用户活动分配一个userInfo字典。稍后将使用它来修复应用程序的状态。一个字符串值被分配给活动的标题属性。这就是将出现在Spotlight搜索结果中的内容。为了确保可搜索的内容不限于应用的标题,您还提供了一系列关键字。在上面的代码片段中,关键字列表包含每个节目的名称及其流派。接下来,您将一些属性分配给NSUserActivity对象以告诉操作系统您希望用户活动执行什么操作。在本教程中,我们只查看搜索组件的API,因此我们禁用Handoff并启用搜索。最后,调用用户活动的becomeCurrent方法,此时它会自动添加到设备的搜索结果索引中。在上面的实现代码中,您可能已经注意到两个注释语句。虽然我们不会在本教程中使用这些属性,但了解每个属性的作用很重要。在上面的实现代码中,每个节目的用户活动和搜索结果仅在应用程序打开时创建。当您使您的用户活动符合eligibleForPublicIndexing时,Apple开始观察此特定活动在用户搜索结果中的作用和交互。如果搜索结果被很多用户使用,Apple会将用户活动提升到自己的云索引中。一旦用户活动在云索引中,任何安装了您的应用程序的人都可以搜索到它,无论他们是否打开了内容。只有当且仅当应用程序的所有用户都可以使用活动时,才能将此属性设置为true。用户活动可以有一个可选属性expirationDate。设置此属性后,您的用户活动将仅在设置的时间段之前显示在搜索结果中。现在您已经知道如何创建一个在Spotlight中显示搜索结果的NSUserActivity,让我们来试验一下。构建并运行您的应用程序,然后在您的应用程序中打开一些程序。完成此操作后,返回主页(在iOS模拟器中按Command-Shift-H)并向下滑动或滑动到最左侧的屏幕以拉起搜索框视图。在搜索框中填写你打开过的程序的标题,你会看到它显示在搜索结果中,如下图。或者,输入您已经打开的节目的类别。由于您已将关键字信息分配给用户活动,因此这也会导致该节目被列在搜索结果列表中。您的应用程序内容已被操作系统正确索引,结果显示在Spotlight中。但是,当您点击搜索结果时,您的应用不会将用户带到他们想要的搜索结果,而只是拉出该应用。#p#幸运的是,借助Handoff,您可以使用NSUserActivity类来恢复应用程序中的正确状态。为了使这成为可能,我们需要实现两种方法。如下面所示在AppDelegate类里实际应用(_:continueUserActivity:restorationHandler:)方法:funcapplication(application:UIApplication,continueUserActivityuserActivity:NSUserActivity,restorationHandler:([AnyObject]?)->Void)->Bool{letsplitController=self.window?.rootViewControlleras!UISplitViewControllerletnavigationController=splitController.viewControllers.firstas!UINavigationControllernavigationController.topViewController?.restoreUserActivityState(userActivity)returntrue}接下来,在MasterViewController类里实现restoreUserActivityState方法:overridefuncrestoreUserActivityState(activity:NSUserActivityState).{ifuser=InfoactivityState(activity:NSUserActivityState)."]as?String,letgenre=activity.userInfo?["genre"]as?String,lettime=activity.userInfo?["time"]as?NSDate{letshow=Show(name:name,genre:genre,time:time)self.showToRestore=showself.performSegueWithIdentifier("showDetail",sender:self)}else{letalert=UIAlertController(title:"Error",message:"从userInfo检索信息时出错:\n\(activity.userInfo)",preferredStyle:.Alert)alert.addAction(UIAlertAction(title:"Dismiss",style:.Cancel,handler:nil))self.presentViewController(alert,animated:true,completion:nil)}}在写这篇文章的时候,最新版本的Xcode7(Beta3)出现了一个问题,用于修复的用户Activity的userInfo属性会变空,这就是为什么我会handleerrorsanddisplayAwarningaboutuserInfo(由操作系统返回).再次编译并运行你的应用程序,并搜索一个节目。当你在搜索结果中点击一个节目时,应用程序将带你直接进入详细信息视图controllerandShowsthecurrentinformationoftheprogramyouselected.2.使用CoreSpotlight框架iOS9中另一个可以让你的内容可以被用户搜索到的API是CoreSpotlight框架,这个框架有类数据库的设计,可以给你提供有关您想成为的内容的更多信息搜索。在您可以使用CoreSpotlight框架之前,我们需要将此项目与此框架链接起来。在ProjectNavigator中,选择该项目并打开顶部的BuildPhases选项卡。接下来,展开LinkBinaryWithLibraries区域并单击加号按钮。在弹出的菜单中,搜索CoreSpotlight并将您的项目链接到此框架。重复这些步骤以链接MobileCoreServices框架。接下来,为了确保我们的APP提供的搜索结果确实来自CoreSpotlight,在你的测试机或模拟器上删除你的应用程序,并在DetailViewController类中注释掉以下语句:activity.becomeCurrent()最后,打开MasterViewController.swift和在Show结构定义前添加如下语句:importCoreSpotlightimportMobileCoreServices接下来在MasterViewController类的viewDidLoad方法中添加如下代码:nameletdateFormatter=NSDateFormatter()dateFormatter.timeStyle=.ShortStyleattributeSet.contentDescription=show.genre+"\n"+dateFormatter.stringFromDate(show.time)varkeywords=show.name.componentsSeparatedByString("")关键字.append(show.genre)attributeSet.keywords=keywordsletitem=CSSearchableItem(uniqueIdentifier:show.name,domainIdentifier:"tv-shows",attributeSet:attributeSet)searchableItems.append(item)}CSSearchableIndex.defaultSearchableIndex().indexSearchableItems(searchableItems){(error)->Voidiniferror!=nil{print(error?.localizedDescription)}else{//Itemswereindexedsuccessfully}}在验证这段代码之前,我们先看一下for循环中的每一步。您创建一个CSSearchableItemAttributeSet对象并将内容传递给项目类型(内容类型)。例如,如果您的搜索结果链接到一张照片,那么您应该传入kUTTypeImage常量。为属性集的title属性分配一个标题。就像NSUserActivity一样,这个标题将出现在搜索结果列表的顶部。接下来,创建一个描述性字符串并将其分配给可搜索属性集的contentDescription属性。该字符串将显示在Spotlight中搜索结果的标题下方。从搜索结果中创建关键字数组,就像在NSUserActivity中一样。最后,创建一个CSSearchableItem,它有一个唯一的项目标识符,一个唯一的域标识符(用于聚合CSSearchableItem项目)和一个属性集(attributeset)。与NSUserActivity不同,NSUserActivity从搜索结果中返回用户活动,当你的搜索结果被用户选中时,你为CSSearchableItem设置的所有唯一标识符信息是你唯一能从操作系统获取的信息。您需要使用这些标识符将您的应用程序恢复到正确的状态。为每个电视节目创建一个CSSearchableItem后,您可以使用带有默认CSSearchableIndex对象的indexSearchableItems(_:completionHandler:)方法为它们编制索引。编译并运行您的应用程序,您的所有节目都将被Spotlight索引。转到搜索页面并搜索其中一个节目。CoreSpotlight搜索结果的处理方式与NSUserActivity中的相同,但过程略有不同。当在搜索结果中选择CSSearchableItem项目时,系统会为您创建一个NSUserActivity对象,其中包含有关所选项目的唯一标识符的信息。在应用委托的application(_:continueUserActivity:restorationHandler:)方法中,您可以使用以下实现代码从CoreSpotlight搜索结果中获取您想要的信息:ifuserActivity.activityType==CSSearchableItemActionType{ifletidentifier=userActivity.userInfo?[CSSearchableItemActivityIdentifier]as?String{//Useidentifiertodisplaythecorrectcontentforthissearchresultreturntrue}}使用CoreSpotlight框架索引APP内容的一个好习惯是删除不再需要的项目。CSSearchableIndex类提供了三种删除可搜索项的方法:deleteAllSearchableItemsWithCompletionHandler(:)deleteSearchableItemsWithDomainIdentifiers(:completionHandler:)deleteSearchableItemsWithIdentifiers(_:completionHandler:)defaultSearchableIndex().deleteSearchableItemsWithDomainIdentifiers(["tv-shows"]){(error)->Voidiniferror!=nil{print(error?.localizedDescription)}else{//Itemsweredeletedsuccessfully}}编译并再次运行您的应用程序。当您尝试搜索任何节目时,不会返回任何结果,因为它们已从索引中删除。3.结合NSUserActivity和CoreSpotlightiOS9中NSUserActivity类的另一个新特性是contentAttributeSet属性。此属性允许您分配一个CSSearchableItemAttributeSet,就像您之前创建的那样。此属性集允许NSUserActivity对象的搜索结果显示与CoreSpotlight搜索结果相同数量的详细信息。首先将以下导入添加到DetailViewController.swift的顶部:importCoreSpotlightimportMobileCoreServices接下来,使用以下实现代码更新DetailViewController类的configureView方法:funcconfigureView(){//Updatetheuserinterfaceforthedetailitem.ifself.nameLabel!=nil&&self.detailItem!=nil{自我.nameLabel.text=detailItem.nameself.genreLabel.text=detailItem.genreletdateFormatter=NSDateFormatter()dateFormatter.timeStyle=.ShortStyleself.timeLabel.text=dateFormatter.stringFromDate(detailItem.time)letactivity=NSUserActivity(activityType:"com.tutsplus.iOS-9-Search.displayShow")activity.userInfo=["name":detailItem.name,"genre":detailItem.genre,"time":detailItem.time]activity.title=detailItem.namevarkeywords=detailItem。姓名。componentsSeparatedByString("")keywords.append(detailItem.genre)activity.keywords=Set(keywords)activity.eligibleForHandoff=falseactivity.eligibleForSearch=true//activity.eligibleForPublicIndexing=true//activity.expirationDate=NSDate()letattributeSet=CSSearchableItemAttributeSet(itemContentType:kUTTypeItemasString)attributeSet.title=detailItem.nameattributeSet.contentDescription=detailItem.genre+"\n"+dateFormatter.stringFromDate(detailItem.time)activity.becomeCurrent()上次编译}}APP,然后打开一些节目。当您搜索节目时,您会看到您的结果,以及创建的NSUserActivity,其详细程度与CoreSpotlight搜索结果相同。总结在本教程中,您学习了如何使用NSUserActivity类和CoreSpotlight框架使您的应用程序中的内容可被iOSSpotlight索引。我还向您展示了如何使用这两个API为您的应用程序中的内容编制索引,以及如何在用户选择搜索结果时恢复您的应用程序状态。iOS9中引入的新搜索API易于使用,可以让用户更轻松地发现和参与应用中的内容。与往常一样,如果您有任何意见或问题,请将其放入下面的评论框中。
