Combining 'AND' and 'OR' Condition in NSPredicate
For Swift, this is how you can do it:
SWIFT 4.x - AND
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p0, p1])
SWIFT 4.x - OR
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [p0, p1])
SWIFT 4.x - NOT
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(notPredicateWithSubpredicates: [p0, p1])
Example
This is an example from one of my codes, where I look for uid and sync:
let p0 = NSPredicate(format: self.uid + " = '" + uid + "'")
let p1 = NSPredicate(format: self.sync + " = %@", NSNumber(value: true as Bool))
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p0, p1])
Another option is to use an NSCompoundPredicate (note andPredicateWithSubpredicates does an AND but there are a few options to use, this should be much more efficient than doing 2 searches)
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSCompoundPredicate_Class/index.html#//apple_ref/occ/clm/NSCompoundPredicate/andPredicateWithSubpredicates:)
Addition to @Stuart's answer, you can use NSCompoundPredicate for your OR & AND operations like this.
Obj-C - OR
// OR Condition //
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]];
Obj-C - AND
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];
Swift - OR
let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [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 - OR
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate.init(type: .or, subpredicates: [predicate1,predicate2])
Swift 3 - AND
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2])
I'll do the following using a SUBQUERY
.
[NSPredicate predicateWithFormat@"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", @"aname", value1, value2];
Try it and let me know.
Another solution could be to grab the whole collection subs
and then filter the retrieved set with a predicate to check if elements match for value1
or value2
.
Hope it helps.
Edit
If you follow Eimantas suggestion make to sure to create the right array:
NSNumber valueA = [NSNumber numberWithInt:20];
NSNumber valueB = [NSNumber numberWithInt:90];
NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil];