You Can Pass ‘NO’ as a NSNumber, But You Probably Don’t Want To
When using Core Data, Boolean values as an attribute are represented using NSNumber. That’s all fine and good, but it requires you to use [NSNumber numberWithBool:YES|NO] when you set the value.
NO is defined as:
#define NO (BOOL)0
we have an issue. 0 is also ‘nil’. Just below the definition of NO we see nil:
#define nil 0 /* id of Nil instance */
Since ‘nil’ has to be a valid NSNumber *, you are allowed to pass NO as a NSNumber * parameter. If object ‘foo’ has a method ’setBarOn’ with a declaration of
- (void) setBarOn:(NSNumber *)aBooleanAsANumber; - (NSNumber *) barOn;
You need to make sure you never call that method with NO, as in:
[foo setBarOn:NO];
If you were to try to read the boolValue by hand you’d be OK. Calling ‘boolValue’ on a nil object seems to return 0, which is NO, so you wouldn’t notice the problem. The problem comes in when you use predicates.
I had a predicate that looked like:
“isBarOn == 0â€
If you setBarOn:NO instead of setBarOn:[NSNumber numberWithBool:NO] the instance in question will not be returned by this predicate. Ouch. Fortunately if you were to look at the attribute that had been set to :NO you’ll see it reported as (null), which is a good hint your Boolean got set wrong.
I’m not sure how common this is or not, but it seemed worthy of pointing out. Hopefully it made some sense to someone.

