The website is updating.
Author: Homer
Implement CoreSpotlight framework – make your content searchable
In current iOS system, content of application can be indexed and searched in search panel. This is a good feature for APP developer.
First we need to know what CoreSpotlight framework can do.
The Core Spotlight framework helps your app participate in search by providing ways to index the content within your app (including user-generated content) and manage the on-device index.
Which means, we need to package information of content and provided to iOS system. Therefore, by Apple Developer Document, the steps needed to implement.
To get started indexing app content, perform these steps:
- Create a CSSearchableItemAttributeSet object and specify properties that describe the item you want to index.
- Create a CSSearchableItem object to represent the item. A CSSearchableItem object has a unique identifier that lets you refer to it later.
- If needed, specify a domain identifier so that you can gather multiple items together and manage them as a group.
- Associate the attribute set with the searchable item.
- Add the searchable item to the index.

Like above picture, I set the name, thumbnail, description as meta for content. The following code is how to package necessary data.
The list of content looks like below picture, we can chose to add the items into search list or we remove all of them. Add and Delete buttons perform the action as the code below.

#pragma mark - Spotlight framework
-(void)addToSpotLight:(id)sender{
NSMutableArray * sps = [[NSMutableArray alloc]init];
for (Content * cot in self.items) {
CSSearchableItem * si = [self generateContentToSpotlightSearchAbleItem:cot];
[sps addObject:si];
}
[[CSSearchableIndex defaultSearchableIndex]indexSearchableItems:sps completionHandler:^(NSError * _Nullable error) {
NSString * message=@"Success Add";
if (error) {
NSLog(@"add search able item error: %@",error);
message = @"Fail Add";
}
UIAlertController * alert = [UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}]];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alert animated:YES completion:^{
}];
});
}];
}
-(void)deleteFromSpotLight:(id)sender{
[[CSSearchableIndex defaultSearchableIndex]deleteSearchableItemsWithDomainIdentifiers:@[SpotlightDomain] completionHandler:^(NSError * _Nullable error) {
NSString * message=@"Success Deleted";
if (error) {
NSLog(@"delete items error :%@",error);
message = @"Fail Deleted";
}
UIAlertController * alert = [UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}]];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alert animated:YES completion:^{
}];
});
}];
}
-(CSSearchableItem *)generateContentToSpotlightSearchAbleItem:(Content *)content{
CSSearchableItem * result = nil;
CSSearchableItemAttributeSet * ats = [[CSSearchableItemAttributeSet alloc]initWithItemContentType:(NSString*)kUTTypeImage];
ats.title = content.name;
ats.contentDescription = content.contentDescription;
ats.keywords = @[@"CodeTemplate",@"Homer",content.name];
ats.thumbnailData = UIImagePNGRepresentation([UIImage imageNamed:content.name]);
result = [[CSSearchableItem alloc]initWithUniqueIdentifier:[[content.objectID URIRepresentation] absoluteString] domainIdentifier:SpotlightDomain attributeSet:ats];
return result;
}
By the code above, I set the keywords for each item. Keywords are indexed for spotlight search. It is a very important attribute.
When you select item from spotlight search list. we can present the detail page about this image. And how to handle the selection, we can use following function of AppDelegate.
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
if ([userActivity.activityType isEqualToString:CSSearchableItemActionType]) {
[LoadNotificationViewController showWithUserActivity:userActivity];
return YES;
}
return NO;
}
//In LoadNotificationViewController
+(void)showWithUserActivity:(NSUserActivity *)userActivity{
NSLog(@"%@",userActivity);
NSManagedObjectContext * context = [[TemplateUtility shareInstance] coredataManagerContext];
NSString * objectIdString = [userActivity.userInfo objectForKey:CSSearchableItemActivityIdentifier];
NSURL * theURL = [NSURL URLWithString:objectIdString];
NSManagedObjectID * objectID = [context.persistentStoreCoordinator managedObjectIDForURIRepresentation:theURL];
Content * c = [Content getContentWithId:objectID withContext:context];
if (c) {
... ...
}
}
In useractivity, there are userInfo which is a NSDictionary that contains meta data about this content. When I print out this dictionary, the result as following image.

Above is a implement of spotlight framework. More code can be found in GitHub CodeTemplate. If you have any suggestions and questions about this blog, please feel free to leave a comment. I will appreciate that.
Some useful notes
for Vim.
yy:copy the line
dd:delete the line
p:to paste the copied or deleted text after the current line
P:to paste the copied or deleted text before the current line
Some useful commands
//list the size of file under this directory
du -h --max-depth=1 | sort -hr
//grep thread that has name "ChildProcessorLinkProcess" and kill them
ps -ef | grep ChildProcessorLinkProcess | grep -v grep | awk '{print $2}' | xargs kill
//find files with name 'naught.*' and rm it
find . -name "naught.*" -exec rm -i {} \;
Git configuration for short cut comments
[core]
editor= /usr/bin/vim
[user]
email = homerzhm@gmail.com
name = Homer Zuo
[color]
branch = auto
diff = auto
status = auto
[color "branch"]
current = red reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan
[alias]
st = status -s
cl = clone
ci = commit -s
cm = commit -m
cma = commit -a -m
cas = commit --amend -s
amend = commit --amend
caa = commit -a --amend -C HEAD
cif = commit --fixup
filelog = log -u
fl = log -u
ai = add --interactive
co = checkout
br = branch
#"!git branch -ra | grep -v done"
bra = branch -ra
#list commands
le = log --oneline --decorate
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
ls1 = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate
lds = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]\\ %C(green)%ad" --decorate --date=short --graph
ls = log --pretty=format:"%C(green)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]\\ %C(yellow)[%ad]" --decorate --date=relative
#show file change in commit id passed in arguement
lc = "!f() { git ll "$1"^.."$1"; }; f"
lnc = log --pretty=format:"%h\\ %s\\ [%cn]"
ld = log --pretty=format:"%C(yellow)%h\\ %Creset%s%Cred\\ [%cn]\\ %ad%Cblue%d" --decorate --abbrev-commit --date=relative
#list all aliases
la = "!git config -l | grep alias | cut -c 7-"
diff = diff --word-diff
d = diff --word-diff
dc = diff --cached
#list modified files in last commit
dl = "!git ll -1"
#diff last commit
dlc = diff --cached HEAD^
#show code changes in last commit
dr = "!f() { git diff "$1"^.."$1"; }; f"
diffr = "!f() { git diff "$1"^.."$1"; }; f"
branch = branch -ra
bmuser = branch -a --list *smitesh.patel* --merged
bnmuser = branch -a --list *smitesh.patel* --no-merged
buser = branch -a --list $1
#reset commands
r = reset
r1 = reset HEAD^
r2 = reset HEAD^^
rh = reset --hard
rh1 = reset HEAD^ --hard
rh2 = reset HEAD^^ --hard
#git svn
svnr = svn rebase
svnd = svn dcommit
svnl = svn log --oneline --show-commit
#stash
sl = stash list
sa = stash apply
ss = stash save
cp = cherry-pick
grep = grep -Ii
gr = grep -Ii
#grep from root foflder
gra = "!f() { A=$(pwd) && TOPLEVEL=$(git rev-parse --show-toplevel) && cd $TOPLEVEL && git grep --full-name -In $1 | xargs -I{} echo $TOPLEVEL/{} && cd $A; }; f"
#grep on filename
f = "!git ls-files | grep -i"
#rename branch tree to done-
done = "!f() { git branch | grep "$1" | cut -c 3- | grep -v done | xargs -I{} git branch -m {} done-{}; }; f"
lasttag = describe --tags --abbrev=0
lt = describe --tags --abbrev=0
#merges
ours = "!f() { git co --ours $@ && git add $@; }; f"
theirs = "!f() { git co --theirs $@ && git add $@; }; f"
#push
pushremote = "!f() { git push -f origin sp/"$1":dev/"$USER"/"$1"; }; f"
deleteremote = "!f() { git push -f origin :dev/"$USER"/"$1"; }; f"
updateSubmodules = "submodule foreach 'git fetch origin --tags; git checkout master; git pull' && git pull && git submodule update --init --recursive"
[push]
default = matching
[rerere]
enabled = true
[mergetool]
keepBackup = false
It will keep Updating…