Is there an example code for corespotlight search feature - iOS 9 API? Really appreciate if can look at sample code to implement/test.
Is there an example code for corespotlight search feature - iOS 9 API?
15.7k views Asked by mojo_ AtThere are 6 answers
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}
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;
}
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
Create a new iOS project and add CoreSpotlight and MobileCoreServices framework to your project.
Create the actual CSSearchableItem and associating the uniqueIdentifier, domainIdentifier and the attributeSet. Finally index the CSSearchableItem using [[CSSearchableIndex defaultSearchableIndex]...] as show below.
OK!Test the index!
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]; } }
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; }
Note:
kUTTypeImage
requires that you import the MobileCoreServices framework.