How to add Core Spotlight to index your app content on iOS9? (ADVANCED)- iOS9 Feature (Part 4)

I’ve mentioned about “How to add Core Spotlight to index your app content on iOS9?” in this article. If you haven’t read it, I really recommend you do.

This article will be about how to add multiple search item in very little and efficient code writing. Search items have some features such as title, contentDescription, rating, unique identifier , thumbData which will show the icon of your special content or basically your application, and so on.

Basically there are two advanced concepts you should know about CSSearchableItems / CoreSpotlight.

First one is your user can navigate anywhere in your app, by understanding which search item is tapped by your user in Spotlight. You can be sure of your users will find anything they search, by navigating them true navigation point of application.

Apple serves very basic app delegate method :

– (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler;

Second one is that you can list your search items and their attributes in a very simple but handy property list (plist) file and creating a very simple singleton class you can call it SearchManager, will help you to separate your search methods from other app delegate methods.

Screen Shot 2016-01-18 at 21.36.06
SearchableItems.plist

Soo, let’s start!

In delegate of your application, you should call your SearchManager for initializing to index searchable items at spotlight.

APPDELEGATE.

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
   [[SearchManager sharedInstance] initializeSpotlightSearch];
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler{

   if([userActivity.activityType compare: @"com.apple.corespotlightitem"]== NSOrderedSame){
      [[SearchManager sharedInstance] navigateFromSpotlightSearchItemContinueUserActivity:userActivity];
   }
return YES;
}

SearchManager.

You can find a brief explanation for following SearchManager code for Spotlight search.

#import "SearchManager.h"

@implementation SearchManager

static SearchManager *sharedInstance = nil;

NSString *const UNIQUE_IDENTIFIER_KEY       = @"uniqueIdentifier";
NSString *const DOMAIN_IDENTIFIER_KEY       = @"domainIdentifier";
NSString *const TITLE_KEY                   = @"title";
NSString *const CONTENT_DESCRIPTION_KEY     = @"contentDescription";
NSString *const THUMBNAIL_DATA_KEY          = @"thumbnailData";
NSString *const NAVIGATION_URL_KEY          = @"navigationURL";
NSString *const KEYWORDS_KEY                = @"keywords";
NSString *const KEYWORD_KEY                 = @"keyword";

+ (SearchManager *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[super allocWithZone:NULL] init];
    }
    
    return sharedInstance;
}

-(void)initializeSpotlightSearch{
//You should check if application is running iOS9 + devices,
//Otherwise your application will crash on iOS7 or iOS8 devices. 
    if(IS_IOS9_OR_GREATER){

        NSMutableArray *searchableItemList = [self getCSSearchableItemList];
        
        CSSearchableIndex *defaultSearchableIndex = [CSSearchableIndex defaultSearchableIndex];
        [defaultSearchableIndex indexSearchableItems:searchableItemList completionHandler:^(NSError * _Nullable error) {
            if (error)
                DLog(@"print error: %@", error.description);
            else
                DLog(@"indexed successfully");
        }];
    }
    
}

+ (NSDictionary *)getPropertyFileBySource:(NSString *)source andRoot:(NSString *)root {
    
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *plistPath = [bundle pathForResource:source ofType:@"plist"];
    NSDictionary *serachableItemsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
    return serachableItemsDictionary[root];
    
}

-(NSDictionary*) getSearchableItemsPlistDictionary{
    return [SearchManager getPropertyFileBySource:@"SearchableItems" andRoot:@"spotlightSearchItems"];
}
- (NSMutableArray*)getCSSearchableItemList{
    NSDictionary *searchableItemsClientDictionary = [self getSearchableItemsPlistDictionary];
    
    return [self getCSSearchableItemList:searchableItemsClientDictionary];
}

- (NSMutableArray*)getCSSearchableItemList:(NSDictionary *)searchableItemsClientDictionary {
    
    NSMutableArray *searchableItemList = [[NSMutableArray alloc]init];
    
    for (NSString *searchableItemDictKey in [searchableItemsClientDictionary allKeys]) {
        NSDictionary *searchableItemDict = [searchableItemsClientDictionary objectForKey:searchableItemDictKey];
        
        NSString *uniqueIdentifier=[searchableItemDict objectForKey:UNIQUE_IDENTIFIER_KEY];
        NSString *domainIdentifier=[searchableItemDict objectForKey:DOMAIN_IDENTIFIER_KEY];
        NSString *contentDescription=[searchableItemDict objectForKey:TITLE_KEY];
        NSString *displayName=[searchableItemDict objectForKey:CONTENT_DESCRIPTION_KEY];
        NSString *title=[searchableItemDict objectForKey:TITLE_KEY];
        NSString *thumbnailData=[searchableItemDict objectForKey:THUMBNAIL_DATA_KEY];
        NSDictionary *keywords = [searchableItemDict objectForKey:KEYWORDS_KEY];
        
        NSMutableArray *keywordsArray = [[NSMutableArray alloc]init];
        for (NSString *akeywordKey in [keywords allKeys]) {
            [keywordsArray addObject:keywords[akeywordKey]];
        }
                
        
        CSSearchableItemAttributeSet *searchableItemAttributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:uniqueIdentifier];
        searchableItemAttributeSet.contentDescription = contentDescription;
        searchableItemAttributeSet.title = title;
        searchableItemAttributeSet.displayName = displayName;
        searchableItemAttributeSet.keywords = keywordsArray;
        if(IsEmpty(thumbnailData)){
            UIImage *thumbnail = [UIImage imageNamed:@"AppIcon"];
            searchableItemAttributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.7);
        }
        
        CSSearchableItem *searchableItem = [[CSSearchableItem alloc] initWithUniqueIdentifier:uniqueIdentifier
                                                                             domainIdentifier:domainIdentifier
                                                                                 attributeSet:searchableItemAttributeSet];
        
        [searchableItemList addObject:searchableItem];
        
    }
    return searchableItemList;
}

-(NSString*) getNavigationURLForSearchableItemKey:(NSString*)searchableItemKey{
    NSDictionary *searchableItemsClientDictionary = [self getSearchableItemsPlistDictionary];
    NSDictionary *searchItem = searchableItemsClientDictionary[searchableItemKey];
    if(!IsEmpty(searchItem)){
        return (NSString*)searchItem[NAVIGATION_URL_KEY];
    }
    return @"";
}
-(void) navigateFromSpotlightSearchItemContinueUserActivity:(NSUserActivity *)userActivity{
    NSDictionary *searchUserInfo = userActivity.userInfo;
    NSString *activityIdentifier = searchUserInfo[CSSearchableItemActivityIdentifier];
  //  NSString *activityType = searchUserInfo[CSSearchableItemActionType];
    
    NSString *navigationURL = [self getNavigationURLForSearchableItemKey:activityIdentifier];
    if(!IsEmpty(navigationURL)){
        // To do - write your codes for navigation, here.
    }
}

If you don’t want to navigate the spesific point at your application. You can ignore these following methods.
-(void) navigateFromSpotlightSearchItemContunieUserActivity:(NSUserActivity*)userActivity;
-(NSString*)getNavigationURLForSearchableItemKey:(NSString*) searchableItemKey;

PS: If you find this article useful please use like button┬á­čÖé┬áand if you have a question or a comment, donÔÇÖt hesitate to share it!

May the Force Touch be with you! ­čÖé┬á

Advertisements

How to add Core Spotlight to index your app content on iOS9? – iOS9 Feature (Part 4)

Apple Says That;

When you make your content searchable, users can access activities and content deep within your app through Spotlight and Safari search results, Handoff, and Siri suggestions.

Point of an developer’s view, main aim of content indexing on iOS9┬áis to┬áhelp┬áyou make your content available in the appropriate index, drive┬áuser engagement and maybe free marketing :D.Read More »