iOS9 SpotLight新功能(1)

iOS9推出后,为了顺应时代,给自己项目加了个Spotlight搜索功能,下面是使用过程中的一点记录

在iOS9中提供了新的APIs,允许你去索引APP里面的内容或者界面状态,通过Spotlight来快速显示APP中的内容。 这些新的搜索APIs的三大组件为:

  • NSUserActivity (iOS8 出现的类,提供handoff功能支持)
  • Core Spotlight (新库,提供Spotlight索引APP内容的功能)
  • web markup(鬼知道什么东西,看名字不像APP开发用的)

1、NSUserActivity

最开始NSUserActivity是iOS8的新特性:HandOff功能所使用的API,用于保存和复原APP的状态。由于项目对HandOff并没啥友好性,所以去年也没有太多的研究,顺道学习一下。
学习链接

简单的说,使用NSUserActivity主要有以下几点:

  • unique identifier(唯一的标识符,通过此标识符,可以链接不同设备的同一APP,也是能实现HandOff功能的基础)
 NSUserActivityTypes
 
  com.xxx.iOS-9-Search.displayShow
 
  • 保存一个UserActivity
NSUserActivity * activity = [[NSUserActivity alloc] initWithActivityType:@"com.xxx.iOS-9-Search.displayShow"];
        
activity.title = @"test";
activity.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:item.name, @"name", item.id, @"id", nil];
        
[activity becomeCurrent];
  • 恢复restore
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
  • update UserActivity
[activity addUserInfoEntriesFromDictionary:dic];

上面4点是NSUserActivity使用过程中需要用到的主要情景。实例化的NSUserActivity对象,可以通过属性retain住,根据情况调用update方法,更新userActivity的userInfo(dictionary)

  • 其他
    eligibleForHandoff,eligibleForSearch:两个属性,区分HandOff和SpotLight。

    expirationDate:当这个属性被设置时,你的user activity 只会在设置的时期之前才会展示在搜索结果里。
    

2、Core Spotlight

当然,先导入最新的库CoreSpotlight.framework
使用起来非常简单,通常在获取网络数据返回后,讲获得数据item,添加到searchIndex中。

    NSMutableArray *items = [NSMutableArray array];
    for (likeItem *item in self.Model.likeItems) {
        CSSearchableItemAttributeSet * attrSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:@"text"];
        NSString *title = item.forumName;
        [attrSet setTitle:title];
        NSString *desc = [NSString stringWithFormat:@"bar"];
        [attrSet setContentDescription:desc];
        CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:item.uniqueIdentifier domainIdentifier:@"like items" attributeSet:attrSet];
        [items addObject:item];
    }
    [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:items completionHandler:^(NSError * _Nullable error) {
        
    }];

添加完搜索索引以后,与userActivity相同,通过spotLight搜索到的内容,点击需要跳转到我们自己的app中,并能够跳转到对应的界面。


- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
    UITabBarController *tabBarController = (UITabBarController *)[self getTabBarController];
    UIViewController *vc = [tabBarController viewControllerAtIndex:0];
    [vc restoreUserActivityState:userActivity];
    return YES;
}

3、NSUserActivity与Spotlight相结合

在iOS9中NSUserActivity类的新增特性就是contentAttributeSet属性。这个属性允许你赋予一个CSSearchableItemAttributeSet, 正如你先前创建的那个。这个属性集合(attribute set)允许NSUserActivity对象的搜索结果可以展示如同 Core Spotlight搜索结果那样的相同数量的详细信息。

但是,在尝试两者结合时,遇到了一些问题,首先,activity中构造的userInfo字典不能够搜索完了restore,userInfo中只包涵一个key:(妈蛋,为啥上不了图)

  kCSSearchableItemActivityIdentifier

这个key从哪来的呢?

     CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:item.uniqueIdentifier domainIdentifier:@"like items" attributeSet:attrSet];

就是这句话,kCSSearchableItemActivityIdentifier的Value就是CSSearchableItem初始化时,传入的参数uniqueIdentifier

再看下文档里怎么说:

// When opening a document from Spotlight, the application's application:willContinueUserActivityWithType:
// method will get called with CSSearchableItemActionType, followed by  application:continueUserActivity:restorationHandler: with an NSUserActivity where the userInfo dictionary has a single key value pair where CSSearchableItemActivityIdentifier is the key and the value is the uniqueIdentifier used when creating the item.
CORESPOTLIGHT_EXPORT NSString * const CSSearchableItemActionType CS_AVAILABLE(NA, 9_0);
CORESPOTLIGHT_EXPORT NSString * const CSSearchableItemActivityIdentifier CS_AVAILABLE(NA, 9_0);

CS_CLASS_AVAILABLE(NA, 9_0)
@interface CSSearchableItem : NSObject 

- (instancetype)initWithUniqueIdentifier:(nullable NSString *)uniqueIdentifier //Can be null, one will be generated
                        domainIdentifier:(nullable NSString *)domainIdentifier
                            attributeSet:(CSSearchableItemAttributeSet *)attributeSet;

// Should be unique to your application group.
// REQUIRED since this is the way you will refer to the item to update the index / delete it from the index
// Starts with an UUID for ease of use, but you can replace it with an UID of your own before the item is first indexed if you wish.
@property (copy) NSString *uniqueIdentifier;

英文不好也能看懂,关键的方法:
application:willContinueUserActivityWithType:
会自动生成一个NSUserActivity对象,该对象的userInfo中只有一个Key,也就是上面看到的那个key。而对应的value就是在初始化CSSearchableItem时,传入的参数,相对于你的app,它必须是唯一的,同时,你可以传一个nil,但是,app会自动给你生成一个唯一的,作为restore时的唯一标识。

由此可见可以在CSSearchableItem初始化时,控制传入的参数,达到自己目的。比如,在我的项目中,我希望可以搜索两种信息,简单的说就是希望可以判断搜索内容的类型,并根据该类型跳转到对应ViewController,我是用的方法就是通过传入的uniqueIdentifier来做判断,进而根据其他参数初始化ViewController,跳转到该vc。

这样做挺low的,但是确实实现了我的需求,想来苹果不会搞出这么low的方法,先这样,等下篇文章(2)中,在对实现这个小需求中遇到的问题做进一步的探索,对NSUserActivity与Spotlight的结合问题再搞搞,搞清楚点,特别是那个userinfo字典,到底啥机制,好像初始化了没啥卵用哦,就为了多点信息?

你可能感兴趣的:(iOS9 SpotLight新功能(1))