iOS CoreData NSPredicate to query multiple properties at once

此生再无相见时 提交于 2019-11-29 21:44:06
CaptainRedmuff

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 :)

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:

Onur Var

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])

Complete solution for Swift2

let request = NSFetchRequest(entityName: "Location")
let subPredicate1 = NSPredicate(format: "(name = %@)", searchString)
let subPredicate2 = NSPredicate(format: "(street = %@)", searchString)
let subPredicate3 = NSPredicate(format: "(city = %@)", searchString)

request.predicate = NSCompoundPredicate(type: .OrPredicateType, subpredicates: [subPredicate1, subPredicate2, subPredicate3])
MFarmer

To avoid the warning Incompatible pointer types initializing 'NSCompoundPredicate *_strong' with an expression of type 'NSPredicate *', replace the following:

NSCompoundPredicate * predicate = [NSCompoundPredicate orPredicateWithSubPredicates:subPredicates];

with this:

NSPredicate * predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

Source: NSCompoundPredicate

Fraser Hess over at CISMGF.com has a great search example. You can read the post at http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/

My code based off the post is:

NSArray *searchTerms = [searchText componentsSeparatedByString:@" "];
if ([searchTerms count] == 1) { // Search in name and description
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", searchText, searchText];
    [self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
} else { // Search in name and description for multiple words
    NSMutableArray *subPredicates = [[NSMutableArray alloc] init];
    for (NSString *term in searchTerms) {
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", term, term];
        [subPredicates addObject:pred];
    }
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
    [self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
}

This is may be useful if you want to search multiple properties for anything that matches (eg UISearchControllerDelegate):

NSString *searchFor = @"foo";
NSArray *fields = @[@"Surname", @"FirstName", @"AKA", @"Nickname"]; // OR'd dictionary fields to search
NSMutableArray *predicates = NSMutableArray.new;
for (NSString *field in fields) {
    [predicates addObject:[NSPredicate predicateWithFormat:@"(%K BEGINSWITH[cd] %@)", field, searchFor]];
}
NSPredicate *search = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];

You could then use this, for example, to filter an array of dictionaries:

NSArray *results = [bigArray filteredArrayUsingPredicate:search];

(the BEGINSWITH[cd] is no magic, just means it'll match beginnings of strings and case-insensitive. Change as needed for your match criteria.)

For Swift:

var predicate = NSCompoundPredicate(
        type: .AndPredicateType,
        subpredicates: [predicate1, predicate2]
    )
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!