Is there an example code for corespotlight search feature - iOS 9 API?
Asked Answered
D

6

24

Is there an example code for corespotlight search feature - iOS 9 API? Really appreciate if can look at sample code to implement/test.

Dunn answered 26/6, 2015 at 0:37 Comment(0)
S
39
  1. Create a new iOS project and add CoreSpotlight and MobileCoreServices framework to your project. enter image description here

  2. Create the actual CSSearchableItem and associating the uniqueIdentifier, domainIdentifier and the attributeSet. Finally index the CSSearchableItem using [[CSSearchableIndex defaultSearchableIndex]...] as show below. enter image description here

  3. OK!Test the index!
    enter image description here

Shake answered 10/7, 2015 at 14:37 Comment(8)
Good answer. But you should probably include how the developers implement course of action after a user has selected and index.Nato
HAHA, because most askers just don't know how to begin with CoreSpotlight search APIs. Here just a simple guide.Shake
I wasn't being facetious. This was a good answer but missing elements to fulfill a true answer to this question. It would be good to include for future question seekers.Nato
@DevC Yes, you are right! The framework should be weak-linked for Compatibility!Shake
Is there a limit on the no. of keywords an application can add for spotlight search ?Humility
@GautamJain The document has no explain. In my demo, tens keywords work fine.Shake
how do i add this with an array of objects? it looks really confusing for meVagrancy
what is the point of using the +dataWithData: method in your example?Belen
M
13
CSSearchableItemAttributeSet *attributeSet;
attributeSet = [[CSSearchableItemAttributeSet alloc]
                                 initWithItemContentType:(NSString *)kUTTypeImage];

attributeSet.title = @"My First Spotlight Search";
attributeSet.contentDescription = @"This is my first spotlight Search";

attributeSet.keywords = @[@"Hello", @"Welcome",@"Spotlight"];

UIImage *image = [UIImage imageNamed:@"searchIcon.png"];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
attributeSet.thumbnailData = imageData;

CSSearchableItem *item = [[CSSearchableItem alloc]
                                       initWithUniqueIdentifier:@"com.deeplink"
                                               domainIdentifier:@"spotlight.sample"
                                                   attributeSet:attributeSet];

[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item]
                                 completionHandler: ^(NSError * __nullable error) {
    if (!error)
        NSLog(@"Search item indexed");
}];

Note: kUTTypeImage requires that you import the MobileCoreServices framework.

Manche answered 26/6, 2015 at 1:27 Comment(5)
Looks wrong. The "com.deeplink" should in fact be a unique identifier that uniquely identifies the object you're indexing (like a primary ID from a database, or a GUUID or whatever else). The kUTTypeImage on CSSearchableItemAttributeSet is where you need to set the deep link. The example Apple displayed in their keynote is actually buggy and inconsistent, but the correct example can be seen earlier in the video.Macilroy
I have an app that pulls data from a Parse class, each row in the class is an object that gets put into a PFTableViewCell. What would be best way of indexing those cells so that they can be searched from spotlight?Morgenthaler
I think best way to index data is while saving data in parse class.Manche
It is a user-contributed class. If indexing when saving data into parse class, it would only index for that one person. I'm wanting to index all of them when a user opens the app. Is there a for loop that would work?Morgenthaler
@Ayush, You should replace [NSData dataWithData:UIImagePNGRepresentation(image)] with UIImagePNGRepresentation(image), as that's superfluous.Kehr
N
9

To complete the spotlight search functionality, once you have implemented mayqiyue's answer, you'll be able to see the results in the search but on selection of the result simply your app would open not the related view with related content.

In order to do so, go to your AppDelegate.m and add the following method.

 -(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler

        {

            //check if your activity has type search action(i.e. coming from spotlight search)
            if ([userActivity.activityType isEqualToString:CSSearchableItemActionType ] == YES) {

                //the identifier you'll use to open specific views and the content in those views.
                NSString * identifierPath = [NSString stringWithFormat:@"%@",[userActivity.userInfo objectForKey:CSSearchableItemActivityIdentifier]];

                if (identifierPath != nil) {

                    // go to YOUR VIEWCONTROLLER
                    // use notifications or whatever you want to do so

                    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
                    MyViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewController"];

                    // this notification must be registered in MyViewController
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"OpenMyViewController" object: myViewController userInfo:nil];


                    return YES;
                }

            }


            return NO;
        }

Make sure to import in AppDelegate.m :

 #import <MobileCoreServices/MobileCoreServices.h>
 #import <CoreSpotlight/CoreSpotlight.h>

UPDATE for Swift 2.1

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {

    if #available(iOS 9.0, *) {
        if userActivity.activityType == CSSearchableItemActionType  {

            //the identifier you'll use to open specific views and the content in those views.
            let dict = userActivity.userInfo! as NSDictionary
            let identifierPath  = dict.objectForKey(CSSearchableItemActivityIdentifier) as! String
            if identifierPath.characters.count > 0 {

                let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let mvc: MyViewController = storyboard.instantiateViewControllerWithIdentifier("MyViewController") as! MyViewController

                NSNotificationCenter.defaultCenter().postNotificationName("OpenMyViewController", object: mvc, userInfo: nil)
            }

            return true
        }

    } else {
        // Fallback on earlier versions
            return false

    }

    return false

}

Make sure to import in AppDelegate.swift :

import CoreSpotlight
import MobileCoreServices
Neves answered 20/10, 2015 at 11:48 Comment(0)
B
7

I am using similar implementation as mentioned by @mayqiyue but I am also checking the existence of the item variable for backwards compatibility with iOS 8.

- (void)setupCoreSpotlightSearch
{
    CSSearchableItemAttributeSet *attibuteSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(__bridge NSString *)kUTTypeImage];
    attibuteSet.title = NSLocalizedString(@"Be happy!", @"Be happy!");
    attibuteSet.contentDescription = @"Just like that";
    attibuteSet.keywords = @[@"example", @"stackoverflow", @"beer"];

    UIImage *image = [UIImage imageNamed:@"Image"];
    NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
    attibuteSet.thumbnailData = imageData;

    CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:@"1"
                                                             domainIdentifier:@"album-1"
                                                                 attributeSet:attibuteSet];
    if (item) {
        [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item] completionHandler:^(NSError * _Nullable error) {
            if (!error) {
                NSLog(@"Search item indexed");
            }
        }];
    }
}

To handle the tap on the search item from Spotlight you need to implement following method in your AppDelegate:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
    if ([userActivity.activityType isEqualToString:CSSearchableItemActionType]) {
        NSString *uniqueIdentifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];

        // Handle 'uniqueIdentifier'
        NSLog(@"uniqueIdentifier: %@", uniqueIdentifier);
    }

    return YES;
}
Bough answered 17/10, 2015 at 12:5 Comment(0)
E
3
  1. Write in your main controller Class

    -(void)storeValueForSpotligtSearch {
    
        NSString *bundleIdentifier                      = [[NSBundle mainBundle] bundleIdentifier];
        // **Your Model Array that Contain Data Like attributes Make, Model, Variant and Year and Images**
    
        for (MyCatalogeModel *myCatalogeModelObj in yourDataContainer) {
            NSMutableArray *arrKeywords                 = [[NSMutableArray alloc] initWithObjects: myCatalogeModelObj.year, myCatalogeModelObj.make, myCatalogeModelObj.model, myCatalogeModelObj.variant, nil];
            NSString *strIdentifier                     = [NSString stringWithFormat:@"%@.%@",bundleIdentifier, myCatalogeModelObj.carId];
            self.userActivity                           = [[NSUserActivity alloc]initWithActivityType:strIdentifier];
            self.userActivity.title                     = myCatalogeModelObj.year;
            self.userActivity.title                     = myCatalogeModelObj.make;
            self.userActivity.title                     = myCatalogeModelObj.model;
            self.userActivity.title                     = myCatalogeModelObj.variant;
            self.userActivity.eligibleForSearch         = YES;
            self.userActivity.eligibleForPublicIndexing = YES;
            self.userActivity.eligibleForHandoff        = YES;
            CSSearchableItemAttributeSet * attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeJSON];
            attributeSet.title                          = myCatalogeModelObj.make;
            attributeSet.thumbnailData                  = [NSData dataWithContentsOfURL:[NSURL URLWithString:[myCatalogeModelObj.imageArray objectAtIndex:0]]];
            attributeSet.contentDescription             = [NSString stringWithFormat:@"%@ %@ %@ %@", myCatalogeModelObj.year, myCatalogeModelObj.make, myCatalogeModelObj.model, myCatalogeModelObj.variant];
            attributeSet.keywords                       = arrKeywords;
            CSSearchableItem *item                      = [[CSSearchableItem alloc] initWithUniqueIdentifier:strIdentifier domainIdentifier:@"spotlight.CARS24ChannelPartnerapp" attributeSet:attributeSet];
            [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:@[item] completionHandler: ^(NSError * __nullable error) {
            }];
            self.userActivity.contentAttributeSet       = attributeSet;
            [self.userActivity becomeCurrent];
            [self updateUserActivityState:self.userActivity];
        }
    }
    
  2. Write in App Delegate

    -(BOOL)application:(nonnull UIApplication *) application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * __nullable))restorationHandler {
    
        @try {
    
            NSString *strIdentifier;
            NSNumber *numScreenId;
            NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
            NSLog(@"Activity = %@",userActivity.userInfo);
            if (userActivity.userInfo[@"vc"]) {
                numScreenId = userActivity.userInfo[@"vc"];
            }
            else{
                strIdentifier = [userActivity.userInfo objectForKey:@"kCSSearchableItemActivityIdentifier"];
                NSLog(@"strIdentifier : %@",strIdentifier);
                NSArray *arr = [strIdentifier componentsSeparatedByString:@"."];
                NSString *strScreenId = [arr objectAtIndex:3];
                NSLog(@"ID -= %@",strScreenId);
    
                **// On Click in Spotlight search item move your particular view.**
    
                [self moveToParticular:[strScreenId intValue]];
                numScreenId = [numFormatter numberFromString:strScreenId];
            }
        }
        @catch (NSException *exception) {}
    
        return YES;
    }
    
Elaterid answered 8/8, 2016 at 13:30 Comment(0)
W
1
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeImage as String)
attributeSet.title = "Searchable Item"
attributeSet.contentDescription = "Code for creating searchable item"
attributeSet.keywords = ["Item","Searchable","Imagine"]
attributeSet.thumbnailURL = NSURL(string: "https://blog.imagine.com/")

let searchableItem = CSSearchableItem(uniqueIdentifier: "com.imagine.objectA", domainIdentifier: "spotlight.search", attributeSet: attributeSet)
CSSearchableIndex.defaultSearchableIndex().indexSearchableItems([searchableItem]) {_ in}
Weatherley answered 3/5, 2016 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.