My app has a UISearchBar allowing user to enter search keywords. Each keystroke executes a Core Data query in order to display the results as text in search bar changes.
The problem is that search bar keystrokes are lagging pretty bad… surely because of slow fetching. Any ideas how to improve the performance?
My Core Data is backed with sqlite data store which contains 1000 objects.
// searchKeyword is the string appears in UISearchBar
// Both title and author may contain several words so I can't use BEGINSWITH
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(author CONTAINS[c] %@) OR (title CONTAINS[c] %@)", searchKeyword, searchKeyword];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:managedObjectContext];
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
[request setFetchLimit:10];
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
execute request and fetch the results
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
NSError* error = nil;
BOOL success = [fetchedResultsController performFetch:&error];
[request release];
Using CONTAINS slows it down. What you need to do is create a new table called searchWords (or whatever), and in that store all the words within your titles, made lower case and with accents removed. These have a relationship linking them back to the original objects. Make sure the word field is indexed.
Perform your query on this table, but instead of using CONTAINS or BEGINSWITH, do something like
word > “term” AND word < “tern”
Note that the first string in there is the search term, and the second is the search term with the last character incremented. This allows Core Data to use the SQL index to perform the search.
Apple have a Core Data WWDC session that explains this, including sample code. The sample code contains a class that handles normalising the string (I.e. Removing case), and incrementing the last character of a word in a unicode aware way.