1

I have a UISearchResultsController which is filtering my NSFetchedResultsController and putting the filtered data into an array. Currently, I use an NSPredicate to take the search bar content and apply the filter. Here's my predicate:

[filteredArray removeAllObjets];
for(Account *account in unfilteredResults){
NSPredicate *predicate;

if(controller.searchBar.selectedScopeButtonIndex == 0){

  predicate = [NSPredicate predicateWithFormat:@"accountFirstName BEGINSWITH[cd] %@", searchString];
}else if(controller.searchBar.selectedScopeButtonIndex == 1){

  predicate = [NSPredicate predicateWithFormat:@"accountLastName BEGINSWITH[cd] %@", searchString];
}else if(controller.searchBar.selectedScopeButtonIndex == 2){

  predicate = [NSPredicate predicateWithFormat:@"group.groupName CONTAINS[cd] %@", searchString];
}

  if([predicate evaluateWithObject:account]){
    [self.filteredArray addObject:account];
  }
}

I'm trying to filter the accounts based on either first name, last name, or group name. I know that these operations are slow, but what can be done to make them faster?

Edit:

I just noticed that I'm recreating the predicate every iteration, but I still think that there should be a better way. I did see something about doing a binary compare in an Apple video, but I have no idea how to convert a search string into a binary string and less how to get the "next greatest" value.

How do I replace the BEGINSWITH statement with something more efficient?

JOM
  • 8,139
  • 6
  • 78
  • 111
Moshe
  • 57,511
  • 78
  • 272
  • 425

2 Answers2

1

It is too old post, but can help to somebody else. With this code you will create only one instance of NSPredicate.

NSPredicate *predicate;

if(controller,searchBar,.selectedScopeButtonIndex == 0){

  predicate = [NSPredicate predicateWithFormat:@"accountFirstName BEGINSWITH[cd] %@",     searchString];
}else if(controller,searchBar,.selectedScopeButtonIndex == 1){

  predicate = [NSPredicate predicateWithFormat:@"accountLastName BEGINSWITH[cd] %@",     searchString];
}else if(controller,searchBar,.selectedScopeButtonIndex == 2){

  predicate = [NSPredicate predicateWithFormat:@"group.groupName CONTAINS[cd] %@", searchString];
}
self.filteredArray = [unfilteredResults filteredArrayUsingPredicate:predicate];
Orifjon
  • 11
  • 1
1

I'm assuming your data objects are CoreData objects, if so have you marked the properties you are searching on as indexed?

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • I believe so. However, how can I mark a relationship as indexed? Is that even possible? – Moshe Jun 29 '11 at 03:54
  • For my fetched properties, I've added an attribute and indexed that. – Moshe Jul 05 '11 at 19:42
  • Yep. I'm only searching a few hundred records. Just to clarify, I denormalized my data so that I don't need to fetch every time I want to use a predicate. – Moshe Jul 05 '11 at 20:46