Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS CoreData NSPredicate to query multiple properties at once

I am trying to use a UISearchBar to query multiple properties of a NSManagedObject I have a NSManagedObject called Person, every person has a name and socialSecurity property. Right now my code can perform a search (fetch) for one of those properties or the other, but not both at the same time.

- (void) performFetch
{       
    [NSFetchedResultsController deleteCacheWithName:@"Master"];  

    // Init a fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MainObject" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Apply an ascending sort for the color items
    //NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Term" ascending:YES selector:nil];
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES selector:@selector(caseInsensitiveCompare:)];    

    NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor];
    [fetchRequest setSortDescriptors:descriptors];

    // Recover query
    NSString *query = self.searchDisplayController.searchBar.text;
    //if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"Term contains[cd] %@", query];
    if(searchValue==1)
    {
        if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
    }
    else {
        if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"socialSecurity contains[cd] %@", query];
    }        

    // Init the fetched results controller
    NSError *error;
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"pLLetter" cacheName:nil];

    self.fetchedResultsController.delegate = self;

    if (![[self fetchedResultsController] performFetch:&error]) NSLog(@"Error: %@", [error localizedDescription]);

    [self.tableView reloadData];
}

I don't know how to put both properties into this statement...

if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];

Any help or ideas would be greatly appreciated.

like image 292
OscarTheGrouch Avatar asked May 16 '12 02:05

OscarTheGrouch


3 Answers

You could use a NSCompoundPredicate.

Like this:

NSPredicate *predicateName = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
NSPredicate *predicateSSID = [NSPredicate predicateWithFormat:@"socialSecurity contains[cd] %@", query];
NSArray *subPredicates = [NSArray arrayWithObjects:predicateName, predicateSSID, nil];

NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

request.predicate = orPredicate;

there is a NSCompoundPredicate for AND too: andPredicateWithSubpredicates:

like image 151
Matthias Bauch Avatar answered Nov 15 '22 04:11

Matthias Bauch


You can append multiple search terms in an NSPredicate using the usual boolean operands such as AND/OR.

Something like this should do the trick.

[NSPredicate predicateWithFormat:@"name contains[cd] %@ OR ssid contains[cd] %@", query, query];

Hope that helps :)

like image 27
Zack Brown Avatar answered Nov 15 '22 04:11

Zack Brown


Addition to @Matthias's answer, you can also use NSCompoundPredicate for your AND operations like this.

Obj-C - AND

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];

Swift - AND

let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate  = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] )

Swift 3 - AND

    let predicate1 = NSPredicate(format: "X == 1")
    let predicate2 = NSPredicate(format: "Y == 2")
    let predicateCompound = NSCompoundPredicate(type: .and, subpredicates: [predicate1,predicate2])
like image 28
Onur Var Avatar answered Nov 15 '22 04:11

Onur Var