iOS 9.0
系统以后,下拉屏幕或者向右滑到最后会显示”spotlight”页面(不支持以下可以升级到iOS9的设备:iPhone
4S,iPad 2,iPad第三代,iPad mini, iPod touch第5代)

原文地址

  • NSUserActivity类是iOS8用来实现handoff的,
    iOS9中提供的新方法帮助你索引用户活动, 导航点. 它即支持私有内容,
    也支持功能内容
  • 下面展示通过NSUserActivity类来索引一个APP里的内容

iOS9新特性 – Search APIs

在IOS9之前,你只能用spotlight通过app的名字找到对应的app。但随着iOS9
Search APIs
的发布,开发者可以通过在app内部的内容中建立索引,通过搜索关键字来进入到app指定的内容区域。

The 3 APIs

NSUserActivity

The NSUserActivity 在iOS8的 Handoff
使用中有介绍到。到了iOS9中,你可以利用NSUserActivity搜索相关的“活跃信息”。你可以提供一些关键词给这些“活跃信息”,
意味着spotlight可以检索它们。这个操作相当于你在浏览网页的时候,有历史记录的作用一样。用户可以通过spotlight快速的打开最近的“活跃信息”。

Web Markup

Web Markup 允许 apps
映射它们的内容到网页上面,然后方便spotlight在网页中快速检索内容。Apple的索引器将会扮演爬虫的角色,在网页上面检索那些被Markup的内容。这些信息在Safari和Spotlight都可以检索。

Core Spotlight

Core
Spotlight是iOS9中的一个新框架,它允许检索在app中的内容。NSUserActivity在保存用户的历史记录是很有用的;而Core
Spotlight可以检索任何你想要的数据。

使用Core Spotlight APIs

NSUserActivity 和 Web Markup APIs 相对而言是很容易使用的,而 Core
Spotlight 是有一点复杂的。为了演示Core
Spotlight是怎样工作的,我们创建一个比较简单的Demo用来展示朋友列表。然后你点击任意一个朋友的名字,你可以看到朋友的头像的具体信息。在演示具体的流程之前,我们先看看最终效果图。

在演示效果中可以看到,我在spotlight中检索相关朋友信息,可以看到他们的大致信息,然后点击一条信息,便可以跳转到自己app中的具体的朋友详情。

图片 1

 

代码分析:

1.
Demo的结构很简单,就是一个导航控制器,根控制器是一个UITableViewController,用来展示朋友名称列表。我们定义为FriendTableViewController。

2.
当点击列表中的一个朋友名称后,就会跳转到详情页面,我们定义为FriendViewController。

3.
所有的朋友数据信息,我们用一个管理类来管理。我们定义为DataSource。这个管理类的职责:

1)存储所有的朋友数据信息。

2)保存用户信息到Core Spotlight的索引器中。

当然,每一条用户信息对应一个模型,定义如下:

Person.h

 

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *identifer;
@property (nonatomic, copy) NSString *icon;
- (instancetype)initWithName:(NSString *)name identifer:(NSString *)identifer icon:(NSString *)icon;
@end

Person.m

 

 

@implementation Person
- (instancetype)initWithName:(NSString *)name identifer:(NSString *)identifer icon:(NSString *)icon {
    if (self = [super init]) {
        self.name = name;
        self.identifer = identifer;
        self.icon = icon;
    }
    return self;
}
@end

 

DataSource.h的方法列表如下:

 

@interface Datasource : NSObject
- (NSArray *)dataList;
- (Person *)findFriendWithId:(NSString *)identifer;
- (void)savePeopleToIndex;
@end

1)dataList方法就是获取所有的用户列表数据信息。

 

2)findFriendWithId: 方法就是根据用户Id获取模型数据。

3)savePeopleToIndex就是保存所有用户数据信息到Core Spotlight的索引器中。

DataSource.m 文件中的代码

 

@implementation Datasource

- (NSArray *)dataList {
    Person *becky = [[Person alloc] initWithName:@Becky identifer:@1 icon:@becky];

    Person *ben = [[Person alloc] initWithName:@Ben identifer:@2 icon:@ben];

    Person *jane = [[Person alloc] initWithName:@Jane identifer:@3 icon:@jane];

    Person *pete = [[Person alloc] initWithName:@Pete identifer:@4 icon:@pete];

    Person *ray = [[Person alloc] initWithName:@Ray identifer:@5 icon:@ray];

    Person *tom = [[Person alloc] initWithName:@Tom identifer:@6 icon:@tom];

    return @[becky, ben, jane, pete, ray, tom];
}

- (Person *)findFriendWithId:(NSString *)identifer {
    for (Person *p in self.dataList) {
        if ([p.identifer isEqualToString:identifer]) {
            return p;
        }
    }
    return nil;
}

- (void)savePeopleToIndex {
    // prepare
    NSMutableArray *searchableItems = [NSMutableArray array];
    for (Person *p in self.dataList) {
        // Create an attribute set for an item that represents an image.
        CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:@image];
        attributeSet.title = p.name;
        attributeSet.contentDescription = [NSString stringWithFormat:@This is an entry all about the interesting person called %@, p.name];
        attributeSet.thumbnailData = UIImagePNGRepresentation([UIImage imageNamed:p.icon]);

        CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:p.identifer domainIdentifier:@com.ios9daybyday.SearchAPIs.people attributeSet:attributeSet];
        [searchableItems addObject:item];
    }

    // save
    [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:searchableItems completionHandler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@error message:%@, error.localizedDescription);
        }
    }];
}

@end

代码的关键部分就是savePeopleToIndex方法,定义的searchableItems就是用来存储相关的可检索的信息;而代码中的CSSearchableIndex的单例方法indexSearchableItems是真正的将searchableItems中的内容存储到Core
Spotlight中的操作。

 

然后我们看看FriendTableViewController的列表展示页面的主要代码

 

- (void)viewDidLoad {
    [super viewDidLoad];
    Datasource *dataSource = [Datasource alloc];
    self.dataList = [dataSource dataList];

    [dataSource savePeopleToIndex];
}

这里的savePeopleIndex就将内容存储到Core Spotlight中了。

 

现在你运行程序,这些数据将会被存储起来了。当你在spotlight中搜索你的朋友,他们将会出现,效果图如下:

图片 2

此时尝试点击一项,但是它不会跳转到app的指定区域,只会跳转到对应的app,因为我们还没有指定要跳转的指定区域。

我们可以在调用continueUserActivity代理方法的时候指定app的行为。代码如下:

 

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler NS_AVAILABLE_IOS(8_0) {

    NSString *friendID = userActivity.userInfo[@kCSSearchableItemActivityIdentifier];
    UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
    [navigationController popToRootViewControllerAnimated:NO];

    FriendTableViewController *friendVC = (FriendTableViewController *)navigationController.viewControllers.firstObject;
    [friendVC showFriendWithId:friendID];

    return YES;
}

第1句代码: 获取你在spotlight中点击的朋友的id。

 

第2、3句代码: 获取到根的导航控制,并且pop掉栈中所有的控制器。

第4句代码: 跳转到app的指定位置。

这里的代码可以可以发现,之前我们保存到Core
SpotLight索引器中的内容现在可以使用userActivity.userInfo字典进行获取了。我们所关心的就是friend
Id,它是被保存到索引器中作为Person这个对象的kCSSearchableItemActivityIdentifier.

正如你所见的,左上角有一个 Back to
search选项,用户可以点击这里返回用户列表。

这篇文章中,并没有涉及到索引器的删除操作,想要了解删除的具体操作,可以参照以下的几个方法:

 

deleteSearchableItemsWithIdentifiers
deleteSearchableItemsWithDomainIdentifiers
deleteAllSearchableItemsWithCompletionHandler

 

– Search APIs
在IOS9之前,你只能用spotlight通过app的名字找到对应的app。但随着iOS9
Search APIs 的发布,开发者可以通过在app内部的内容…

Search API

通过search API可以执行一个查询query并获得与query相匹配的查询结果.
可以在一个或多个indices和一个或多个types中执行. 查询条件可以通过查询java
API来提供,search请求提可以放在SearchSourceBuilder. 例如:

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.QueryBuilders.*;
SearchResponse response = client.prepareSearch("index1", "index2")
        .setTypes("type1", "type2")
        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
        .setQuery(QueryBuilders.termQuery("multi", "test"))                 // Query
        .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))     // Filter
        .setFrom(0).setSize(60).setExplain(true)
        .get();

以上所有参数都是可选的,以下是最小查询代码

// MatchAll on the whole cluster with all default options
SearchResponse response = client.prepareSearch().get();

注意:
Although the Java API defines the additional search types
QUERY_AND_FETCH and DFS_QUERY_AND_FETCH, these modes are internal
optimizations and should not be specified explicitly by users of the
API.

更多有关search operation, 请查看REST
search文档.

图片 3spotlight.png

在 iOS9 之前,你只能在 spotlight
中输入关键字,比如应用名字,搜索到应用。在 iOS9 中苹果提供了一套 Search
APIs。允许开发者选择应用的内容,索引起来供 spotlight
进行搜索,同时可以设置在 spotlight 中的展示效果,以及点击之后如何响应。

图片 4demo.gif

Using scrolls in Java

先读并了解 scroll
documentation
中文介绍

在搜索栏中搜索关键词,会显示不同app的内容,如图一

3个新的搜索相关API

代码示例分析

  • 1.删除系统自带的storyboard,添加一个tableViewController,并且嵌套一个导航控制器;
  • 2.更改ViewController继承UITableViewController,并把ViewController与storyboard关联在一起
  • 3.创建三个继承于UIViewController控制器

2.1添加activity

- viewDidLoad { [super viewDidLoad]; [self addUserActivity]; self.navigationItem.title = @"主界面";}- addUserActivity{ _activity = [[NSUserActivity alloc]initWithActivityType:@"chuanzhang"]; _activity.title = @"Eden"; _activity.keywords = [NSSet setWithArray:@[@"Adam", @"Lilith", @"Eve"]]; _activity.eligibleForHandoff = NO; _activity.eligibleForSearch = YES; // 每个控制器的user activity和 搜索结果都是仅当应用曾经被打开过时而创建的 // _activity.eligibleForPublicIndexing = YES; [_activity becomeCurrent];}

2.2数据展示

#pragma mark UITableView dataSource- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 3;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *identifier = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if  { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } if (indexPath.row == 0) { cell.textLabel.text = @"Adam"; }else if (indexPath.row == 1){ cell.textLabel.text = @"Lilith"; }else if (indexPath.row == 2){ cell.textLabel.text = @"Eve"; } return cell;}

2.3监听cell的点击,实现控制器之间的跳转

#pragma mark UITableView delegate- tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.row == 0) { AdamViewController *adamView = [[AdamViewController alloc]init]; [self.navigationController pushViewController:adamView animated:YES]; }else if(indexPath.row == 1){ LilithViewController *lilithView = [[LilithViewController alloc]init]; [self.navigationController pushViewController:lilithView animated:YES]; }else{ EveViewController *eveView = [[EveViewController alloc]init]; [self.navigationController pushViewController:eveView animated:YES]; }}

图片 5图一.png

NSUserActivity

三.监听在Spotlight中的点击

3.1在AppDelegate方法中监听Spotlight中的点击

- application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(NSArray * _Nullable))restorationHandler{ UINavigationController *navi = (UINavigationController *)self.window.rootViewController; [navi.topViewController restoreUserActivityState:userActivity]; return YES;}

3.2在ViewController中实现跳转

- restoreUserActivityState:(NSUserActivity *)activity{ if ([activity.title isEqualToString:@"Adam"]) { AdamViewController *adamView = [[AdamViewController alloc]init]; [self.navigationController pushViewController:adamView animated:YES]; }else if([activity.title isEqualToString:@"Lilith"]){ LilithViewController *lilithView = [[LilithViewController alloc]init]; [self.navigationController pushViewController:lilithView animated:YES]; }else if([activity.title isEqualToString:@"Eve"]){ EveViewController *eveView = [[EveViewController alloc]init]; [self.navigationController pushViewController:eveView animated:YES]; }}

点击『豆瓣』一栏里的第一行,直接跳入了『豆瓣』app,显示了『荒野猎人』的页面

NSUserAcitivity 在介绍 iOS8 的 Handoff 时引入,iOS9 中允许对这些
activities 进行搜索。你可以提供元数据给这些 activities, 这意味着
sptlight
可以索引这些内容。类似于浏览器展示网页的做法(你打开过的历史页面被记录了下来),用户可以快速的在
Spotlight中搜索,打开最近的 activities。

四.其他三个控制器

由于代码一样,只写一份参考

@interface LilithViewController ()// 注意:必须是强引用@property (nonatomic, strong)NSUserActivity *activity;@end@implementation LilithViewController- viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.navigationItem.title = @"Lilith"; [self addUserActivity];}- addUserActivity{ // 使用唯一标识符 @"lilith"创建一个新的NSUserActivity对象 // 这个工程已经被配置成确保使用这个标识符时要保证它不会被改变 _activity = [[NSUserActivity alloc]initWithActivityType:@"lilith"]; // 这就是将会在Spotlight 搜索结果里出现的内容 _activity.title = @"Lilith"; // 搜索的关键字 // 为了确保可搜寻的内容不仅止限于应用的标题,你也要提供一系列的关键字 _activity.keywords = [NSSet setWithArray:@[@"Lilith"]]; // 是否将用户活动转交到其他设备 _activity.eligibleForHandoff = NO; // 是否显示历史搜索记录 _activity.eligibleForSearch = YES; // 它自动的被加入到了设备的搜索结果索引中 [_activity becomeCurrent]; // 过期时间,比如新闻一周后就过期 // _activity.expirationDate = // 每个控制器的user activity和 搜索结果都是仅当应用曾经被打开过时而创建的 // _activity.eligibleForPublicIndexing = YES;}

图片 6图二.png

Web Markup

这就是SearchAPI的一个用法。

Web Markup 允许应用镜像自己的内容,并在 Spotlight
中建立索引。用户并不需要应用安装在自己的设备上来展示搜索结果。苹果的爬虫自己去抓取你网站上打了
markup 的内容,这些内容稍后会提供给 Safari 和 Spotlight。

官方文档App Search Programming Guide中的介绍是

事实上,这个重要的特性,甚至并不需要用户安装了你的应用在自己的设备上。这样可以将你的应用展示给更多的潜在用户。苹果的云服务,将你的应用的内容索引起来,让你的应用和
public Search APIs 保持一个深度连接。更多关于Web Markup
的内容,可以阅读苹果官方的文档 《Use Web Markup to Make App Content
Searchable》。

Search in iOS 9 gives people great ways to access information inside
of your app, even when it isn’t installed. When you make your content
searchable, users can access activities and content deep within your
app through Spotlight and Safari search results, Handoff, Siri
Suggestions, and Reminders. Making your content searchable helps you
enhance the user experience of your app and improve its
discoverability.

CoreSpotlight

iOS 9
的搜索功能为人们获取app中的信息提供了极大的便利,即便是在该app并未安装的情况下。
当你的app中的内容标记为可搜索时,用户可以通过Spotlight,Safari,Handoff,Siri
Suggestion
,Reminders来获取到这些页面和内容。让你的app的内容可以被搜索到,这能够帮助用户发现你的app,并且提升用户体验。

CoreSpotlight 是 iOS9 提供的新
Freamework,允许你索引你的应用内容。当使用它的
Api,你可以方便的将你喜欢的数据,索引起来,NSUserActivity
帮助存储用户的使用历史。它让你的应用可以底层的和 CoreSpotlight
进行连接,将索引存储在用户设备上。

App search is easy for you to adopt and customize. You don’t need any
prior experience with implementing search, and you control what
content gets indexed, which information to show in search results, and
where the user goes after tapping a result related to your content.

使用 Core Spotlight APIs

App search
功能很容易使用和定制。你自己控制哪些内容是被标记为可搜索的,哪些信息是展示在搜索结果中(spotlight,safari等),用户点击了你的搜索结果之后页面跳去哪里,并不需要在此之前有过implementing
search的经验。

NSUserActivity 和 Markup 更简单和容易使用一些, CoreSpotlight
则相对复杂一些。为了示范Core Spotlight APIs
是怎么工作的,让我们来创建一个简单的应用。这个应用展示我的一个朋友列表,点击朋友的名字可以查看照片。你可以在
Github 上找到源文件。

iOS 9
中隐私性是一个基本的特征。为了在保护用户隐私数据的情况下给用户最好的搜索体验,这里有两种索引方式来存储可被搜索的内容。你可以使用各种搜索相关APIs来对每个item指定合适的索引,因此,明白每种索引是如何工作的就至关重要。

图片 7

iOS 9 provides the following indexes:A private on-device index.
Each device contains a private index whose information is never shared
with Apple or synced between devices. When you make an item available
in a user’s on-device index, only that user can view the item in
search results.Apple’s server-side index. The server-side index
stores only publicly available data that you’ve marked appropriately
on your website

这个应用有一个简单的 storyboard, 包含两个 controller,
FriendTableViewController 展示一个列表,每行显示一个朋友的名字,
FriendViewController 展示朋友的详细信息。

iOS 9 提供了两种索引方式:
  • 私有的设备侧索引。每个设备包含私有的索引,被其索引的信息永远不会跟Apple共享或者在设备之间同步。当一个条目被标记为用户侧索引,只有该设备的用户才能在搜索结果中看到该类目。
  • Apple
    服务器侧索引。服务器侧索引只存储,你的网站上的,已经恰当的标记为公开可见的数据。

图片 8

iOS 9 提供了一些APIs:
  • NSUserActivity类中新增了方法和属性。这些可以帮助你索引用户在app的活动,比如visiting
    a navigtion point ,创建和查看内容。
  • Core Spotlight
    framework。它提供的APIs能把app特定内容添加到用户侧索引,并且开启跳入到你的app的deep
    links。(所谓deep link
    指的是点击spotlight或者safari的搜索结果,跳进你的app中的指定页面)
  • Web markup。这个能把相关的web
    内容可搜索化,帮助你丰富用户的搜索体验。

官方文档给出了下面的信息。

It’s recommended that all apps use NSUserActivity and that they
support Handoff. Using the search-related properties of NSUserActivity
is the best way to show users the information they care about and to
improve the ranking of your search results. As users perform
activities in your app, you use NSUserActivity to add the item to the
on-device index. By default, an item represented by an NSUserActivity
object is private, which means that it is added to the on-device
index. If your content includes activities that all users can view,
you identify them as eligible for public indexing. Learn more about
using NSUserActivity in Index Activities and Navigation Points.

If your app handles persistent user data, such as documents, photos,
and other types of content created by or on behalf of users, use the
Core Spotlight APIs to index the content. Unlike NSUserActivity, Core
Spotlight does not require users to visit the content in order to
index it. In addition, you can use CoreSpotlight APIs to index content
at any point, such as when the app loads. Note that Core Spotlight
helps you make items searchable in the private on-device index; you
don’t use Core Spotlight APIs to make items publicly searchable. Learn
more about using Core Spotlight APIs in Index App Content.

If your app hosts some or all of its content on a website, use web
markup to let Apple’s web crawler (calledApplebot) index your
content in Apple’s server-side index and make it available to all iOS
users in Spotlight and Safari search results. Learn more about using
web markup to make your web content searchable in Mark Up Web Content.
Note that search results generated by web markup are shown in
countries that are supported by Spotlight Suggestions.

苹果推荐所有app 都使用NSUserActivity
来提供Handoff功能。使用NSUserActivity中搜索相关的属性,是展示用户关心的信息,提升在搜索结果中的排名的最好的方式。用户在你的app中操作的时候,你使用NSUserActivity把当前活动增加到用户侧索引中。默认情况下,使用NSUserActivity抽象的条目是私有的,这意味着它被存储在用户侧索引中。如果你的内容中包括所有用户都可见的活动,你应该把这些内容声明为公开。点击Index
Activities and Navigation
Points查看更过关于如何使用NSUserActivity的信息。

如果你的app操作了持久化的信息,比如文档,图片,其他类型的(被用户或者为了用户创建的)内容,那你应该使用Core
Spotlight APIs来索引它们。不同于NSUserActivity,Core
Spotlight并不要求先让用户访问内容才能索引这些。另外,你可以使用CoreSpotlight
APIs在任何节点索引数据,比如在app加载的时候。值得注意的是,使用Core
Spotlight标记的数据都是用户侧的,你并不能把item标记为公开可搜索的。点击Index
App Content查看更多关于使用Core Spotlight APIs的信息。

如果你的app在网站上托管部分或者全部数据,使用web markup
可以让Apple的网页爬虫(叫做Applebot)把内容索引到Apple服务器侧,这使得这些内容在所有iOS
用户的Spotlight 和Safari搜索结果中都是可见的。请注意:使用web
markup生成的搜索结果会展示在Spotlight Suggestions支持的国家。

使用NSUserActivity的索引声明为公开内容有什么作用?我在官方文档里找到这样一段话

In iOS 9, marking a public item as eligible for public indexing also
adds it to the on-device index and confers an additional advantage:
When you use web markup to make your related website content
searchable, user engagement with publicly eligible search results from
your app can help improve the ranking of your website’s content. When
a user taps a searchable activity or state in Spotlight search
results, you use NSUserActivity APIs to continue the activity and
return the user to the relevant area in your app.

在iOS
9中,把一条公共类目标记为eligibleForPublicIndexing也是存储到on-device
index,这给予了更多的功能:当你使用web
markup技术把你的相关网页内容可搜索化时,你的app的公开搜索结果的用户参与度,可以帮助你提升你的网页内容的排名。当用户点击了spotlight
搜索结果中的活动或者状态时,使用NSUserActivity APIs
帮助用户继续之前的活动,返回到app中相关页面。综合上文,使用NSUserActivity把内容标记为公开,可以让安装了app的其它用户搜索到相关信息。举个例子,淘宝电影app。A用户访问了『美人鱼』电影页面,这个时候app内部把该(由美人鱼电影相关信息封装而成)类目标记为公开;然后B用户也执行此操作;C用户,D用户…。当产生了许多个相同标记之后(每个用户访问美人鱼页面在其设备上生成一个标记),没有访问过该页面的X用户Y用户Z用户在spotlight中搜索『美人鱼』,也会出现该搜索结果(需要用户安装淘宝电影app)。

首先,我们重载 Datasource 类的 init() 方法,创建和存储一个包含 Person
对象的数组。你可能希望从数据库中,或者你的服务器加载数据,这里只是为了展示,所以我们选择创建简单的模拟数据。

隐私

这三种APIs ,跟上文说的两种索引方式是对应的。使用NSUserActivity和Core
Spotlight APIs创建的索引都是 on-device index.使用web
markup技术是存储在server-side

As the user uses your app, you create activity objects associated with
various navigation points and app states. Each item is added to the
on-device index by default. In iOS 9, marking a public item as
eligible for public indexing also adds it to the on-device index.

The Core Spotlight framework provides ways to index the content within
your app and manage the private on-device index.The items you index
using Core Spotlight APIs are not added to Apple’s server-side index
or synced between devices.

Because items indexed by Applebot are already public, they are stored
on Apple’s server-side index.

除了使用NSUserActivity 和 Core Spotlight的APIs,增加web
markup之外,你还应该使用三个关键技术来给用户最好的体验。

  • Univeral links。 在iOS 9 之后,使用universal links技术,用standard
    HTTP or HTTPS links取代custom URL schemes。Universal
    links对所有用户有有效:如果用户安装了你的app,link会把他们引入你的app;如果用户没有安装你的app,lin
    会在Safari打开你的网站。点击Support Universal
    Links了解如何使用universal links。

  • Smart App Banners。当用户在Safari中访问你的网页,Smart App Banner
    可以让用户启动你的app或者有机会下载你的app。点击Promoting Apps with
    Smart App Banners了解更多关于Smart App Banners 的信息。

  • Handoff。Handoff
    允许用户从一个设备切换到另一个设备时继续之前的活动。例如,当在Mac浏览一个网页时,在你的iPad上,会直接进入你的原生app中。在iOS
    9 中,Handoff包括了对app search的特殊支持。点击Handoff Programming
    Guide了解更多关于Handoff 的信息。

为了给用户最好的体验,系统会估计用户使用Spotlight或者Safari搜索跳入app的频次。正因为如此,那些用户觉得没什么用的搜索结果会很快的被标记出来,最终不会再搜索结果中展示。iOS
会根据下面的信息来决定搜索结果展示的顺序:

  • 用户通过搜索访问app内容的频次(only NSUserActivity)
  • 用户通过搜索访问app的数量
  • 使用web markup标记的网页的访问量和有效结构化的数据量。

总得来说,你可以通过以下的事情来提供良好的搜索结果以此鼓励用户使用你的app:

  • app内提供优质内容
  • 使用上文提到的搜索APIs来提升搜索结果与你的app的相关姓
  • 尽可能的只把用户最喜欢的数据供搜索使用
  • 必要的情况下通过移除和更新来保持索引的时效性
  • 提供切实丰富的搜索信息来引导用户点击
  • 尽可能的减少,用户点击搜索结果到跳入app展示内容,这个过程消耗的时间

点击 Combine APIs to Increase Coverage andImprove the Ranking of Your
Results来了解更多关于提升用户搜索体验的信息

图片 9

淘宝电影

对照一台没有安装过淘宝电影app 的iOS
9.2系统的iPhone6Plus,实验组也是iPhone6Plus正常使用淘宝电影,访问频次2周一次。试验过程略结果:1.初次安装未打开的情况下搜索当前上映电影并无结果。2.启动过app,停留在列表页,成功收到数据后再次搜索,可以搜索出当前上映电影,即便该并未进入过电影详情;断网后依然可搜索。3.搜索出的结果,断网前后并无区别。4.半年前的电影,两台设备都无法搜索出,但是在淘宝电影app内搜索出该电影(无论是在app搜索列表或者详情页),spotlight就可以搜索到。

分析:淘宝电影app会在首页或者之前,将最近数据索引。用户app内搜索的结果和访问记录也会被索引。使用的API应该是NSUserActivity,但是是否将属性设置为公开,并无结论。

一旦数据存储到了 People 这个数组中,Datasource 类就准备好可以用了。

知乎

分析:知乎也是会索引首页数据和用户访问记录。但是经过断网测试,首页数据的缓存可能是随用户滑动进行,并不是一次性。

现在数据准备好了,在FriendTableViewController 中创建一个 instance, 给
table 的 cell 来展示数据。

百词斩

分析:百词斩的app我用的不多,但是新下载的app,断网后打开app。然后搜索常用单词,都可以搜索到。我怀疑百词斩是直接使用core
spotlight 索引了成千上万个单词和常用短语。

关于Search API的一些使用场景1.展示对应新闻 – 今日头条2.展示问答帖子 –
知乎3.展示电影 – 淘宝电影,豆瓣4.展示电影院 – 淘宝电影5.展示单词 –
百词斩6.展示药品 – 用药助手7.展示地标 – 百度地图具体如何使用Search
APIs,就要看需求而定了。

图片 10

疑惑
  • NSUserActivity
    设置为public的情况,在测试中并未发现具体例子。可能是测试量级较少。
  • 索引数据究竟最多能索引多少?这个我不知道。但是官网上有这样一句话

Core Spotlight APIs work best when you have no more than a few
thousand items.

看样子,至少几千个还是运行的妥妥的。所以,看需求就放心的使用吧。

在 cellForRowAtIndexPath 方法中,展示内容

图片 11

现在,模拟数据已经准备好了。我们用 iOS9 提供的新 API 把他们存储到 Core
Spotlight 中。回到Datasource 类中,我们创建一个 savePeopleToIndex
方法。这个可以在FriendTableViewController的视图加载完成后调用。

图片 12

最后一步是调用 CSSearchableIndex的indexSearchableItems
方法。它会真正的把 items 存储到CoreSpotlight
中,这样用户就可以搜索和展示出结果了。

图片 13

好了,当你运行一下你的应用后,数据就索引起来了,当你在 spotlight
中搜索时,朋友的信息出来了。

图片 14

响应用户的选中事件

现在用户看到了搜索的结果,希望他们会点击一下。但是,如果现在他们点击了,会怎么样呢?只会打开你的应用。如果你希望跳转至展示用户点击的朋友的详细信息,你还需要再做一点点工作。当用户用点击的方式打开应用时。,我们可以通过
UIApplicationDelegate 中的continueUserActivity,具体规定应用的行为。

图片 15

如你所见,我们之前,通过 indexSearchableItems 方法,存储在 CoreSpotligh
t中的信息,现在可以让 userActivity.userInfo
字典使用了。我们唯一感兴趣的是 friend ID, 之前我们 items 的
kCSSearchableItemActivityIdentifier 存储在了索引中。

一旦我们从 userInfo 字典中拿到数据,我们找到应用的 navigation
controller, 然后退到root(不用动画,以免用户察觉异样),然后调用
showFriend 方法。我不详细讲这些了。总之,大体上就是根据 friend ID, 找到
friend 的详细信息的数据,然后 push 了一个新的 ViewController
来展示他。这就是所有的操作了,现在,当用户点击一个结果时,应用被打开,同时到了这个朋友的详细页面。

图片 16

如你所见,在应用左上角有一个“回到搜索”的按钮,可以让用户直接快速的返回到Spotlight,当然也可以在应用中,点击标准按钮,来切换页面。

Demo 总结

在上面的demo中,我们展示了,多么简单就可以把应用的内容索引到
CoreSpotlight
中,对于用户搜索特定内容多么有帮助,多么强大的吸引用户打开你的应用。

我们没有展示如何从索引中移除数据。这对你来说很重要,要时刻保持 spotlight
中的数据是最新的。要了解怎么移除旧的数据,可以翻阅相关文档,查看deleteSearchableItemsWithIdentifiers,
deleteSearchableItemsWithDomainIdentifiers 和
deleteAllSearchableItemsWithCompletionHandler这三个方法。

好公民准则的重要性

看起来存储尽可能多的内容到 Spotlight 和 Safari
中是个好主意,但是希望大家能够在 iOS
的生态系统中做个好公民,遵守让用户高兴的准则。并且 Apple
也会注意到你的行为,他们设置了相关的规则,一旦发现恶意的使用
Spotlight,你的内容很容易被移到搜索的最后。

延伸阅读

想了解更多的关于Search APIs的内容,推荐你收看WWDC 2015的 session 709,
Introducing Search APIs. 你也会对阅读文档《NSUserActivity Class
Reference》和《documentation for CoreSpotlight》感兴趣。

最后,别忘了,如果你想试一试我们刚创建的demo,可以到Githubthub中去下载。

更多内容,请移步 iOS9 Day-by-Day.

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图