How to write a BOOL predicate in Core Data?
IphoneIosIpadCore DataPredicateIphone Problem Overview
I have an attribute of type BOOL
and I want to perform a search for all managed objects where this attribute is YES
.
For string attributes it is straightforward. I create a predicate like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userName = %@", userName];
But how do I do this, if I have a bool attribute called selected and I want to make a predicate for this? Could I just do something like this?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"selected = %@", yesNumber];
Or do I need other format specifiers and just pass YES
?
Iphone Solutions
Solution 1 - Iphone
From Predicate Programming Guide:
You specify and test for equality of Boolean values as illustrated in the following examples:
NSPredicate *newPredicate = [NSPredicate predicateWithFormat:@"anAttribute == %@", [NSNumber numberWithBool:aBool]];
NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == YES"];
You can also check out the Predicate Format String Syntax.
Solution 2 - Iphone
Swift 4.0
let predicate = NSPredicate(format: "boolAttribute == %@", NSNumber(value: true))
Solution 3 - Iphone
Don't convert to NSNumber, nor use double "=="
More appropriate for Swift >= 4:
NSPredicate(format: "boolAttribute = %d", true)
Note: "true" in this example is a Bool (a Struct)
Solution 4 - Iphone
Swift 3
let predicate = NSPredicate(format: "boolAttribute == %@", NSNumber(value: true))
In Swift 3 you should use NSNumber(value: true)
.
Using NSNumber(booleanLiteral: true)
and in general any literal initialiser directly is discouraged and for example SwiftLint (v. 0.16.1) will generate warning for usage ExpressibleBy...Literal
initialiser directly:
> Compiler Protocol Init Violation: The initializers declared in compiler protocols such as ExpressibleByArrayLiteral
shouldn't be called directly. (compiler_protocol_init)
Solution 5 - Iphone
Swift 4
request.predicate = NSPredicate(format: "boolAttribute == %@", NSNumber(value: true))
Swift 3
request.predicate = NSPredicate(format: "field = %@", value as CVarArg)
Solution 6 - Iphone
Swift 3.0 has made a slight change to this:
let predicate = NSPredicate(format: "boolAttribute == %@", NSNumber(booleanLiteral: true))
Solution 7 - Iphone
if you do not want to hard-code the attribute name inside the format you can use #keyPath
with something like,
let samplePredicate = NSPredicate(format: "%K != %d", #keyPath(Foo.attr), true)