If your iPhone app needs to store or access a lot of data locally you should take a look at Core Data. It’s not a panacea, but I find that it’s particularly useful when you need to search a lot of data that may result in a very long list to present in a table view. For this use case the NSFetchedResultsController is your friend. It handles many of the nasty issues of memory management, ensuring that you have enough data in memory to populate the visible portion of the table view instead of loading the entire result set into memory at once.
Your code to perform a fetch using NSFetchedResultsController may look something like this:
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText]; [self.fetchedResultsController.fetchRequest setPredicate:predicate]; NSError *error = nil; [self.fetchedResultsController performFetch:&error];
If you’re using a UISearchDisplayController you may be tempted to call this code each time the user enters a new character in the search field. There may be obvious performance reasons why you cannot want to do this. If it takes a few seconds to perform each fetch after each character then it will make for very slow data entry that will frustrate the user.
But there’s a more subtle reason why this is a bad idea, which I recently ran into.
NSFetchedResultsController optionally caches results and the cache content may get out of sync if you just change the NSPredicate like the code above does. One way to get around this is to delete the cache before you set the new predicate:
[NSFetchedResultsController deleteCacheWithName:nil]; [self.fetchedResultsController.fetchRequest setPredicate:predicate];
I’ve seen the first code section in many Core Data code examples, but I’ve never seen anyone mention the need to delete the cache before you perform another fetch with a different predicate. Now it turns out that you don’t have to do this in the current iPhone SDK, because it “just happens to work” anyway. But this behavior may, or may not, change in an upcoming NDA-covered SDK release. Consider this an advance warning.