UPDATE!
As pointed out by Jeff LaMarche and Julio Barros, there is an easier way to deal with Booleans in Core Data, and it is using Wolf Rentzsch‘s http://rentzsch.github.com/mogenerator/

Original Post:
There are a couple of things that I had trouble with while using a boolean with Core Data. The first was how to update this attribute, and the second was how to properly test against it.

I have an attribute in one of my Core Data entities that is of type Bool in my .xcdatamodel called isDone.

When I first tried to update the value to YES, I tried to do this:

This, quite rightly, gives the warning: “makes pointer from integer without a cast.” That is because Core Data does not support a boolean type. It will create your bool attribute with a type of NSNumber, which I could see when I looked at the header file for my item:

@property (nonatomic, retain) NSNumber * isDone;

So the correct thing to do was save the NSNumber value of NO or YES (0 or 1) by using numberWithBool:

The second wrinkle was when I tried to test the value of this attribute. I first wrote:

If (toDo.isDone)

The problem? This was always returning true! Because it was testing, basically, whether or not the NSNumber stored in the isDone property was nil or not. Even if its value was 0, if (item.isDone) evaluated to true.

What I did instead? Test against the boolValue

If (toDo.isDone.boolValue)

Hurray! And now I can get on with it!



6 Responses to “Core Data and Booleans: Newbie Edition”  

  1. 1 Jeff LaMarche

    You really should check out Wolf Rentzsch’s MoGenerator.

    http://rentzsch.github.com/mogenerator/

    Among the many things it does for you is to setup “value” versions of BOOL and NSNumber accessors so you don’t need to do this extra step. Instead of

    if ([toDo.isDone boolValue])

    You can just do this:

    if (toDo.isDoneValue)

    Plus, it makes your life much better when you need to make changes to your data model – since all the generated code is in a class you never touch (a class between the class your custom subclass and NSManagedObject), you never lose your class’ custom methods because only the superclass gets re-generated, not your custom class.

    In the long run, a huge time and hassle saver.

  2. 2 Julio Barros

    Hi,

    If you have not tried it you may want to give Mogenerator a try. It can be a little confusing to set up at first but once you do it generates model classes for you with methods to access the value of numbers and booleans. So for example you would get methods named isDoneValue that would set and get BOOLS instead of having to do the numberWithBool and boolValue calls yourself. Its a small thing but helps me a lot.

    It does some other cool things and I use it on all my projects. Its free and open source and you can get more info at http://rentzsch.github.com/mogenerator/

    Julio

  3. 3 am

    I knew if I posted this I would get suggestions on how to do this even better! Thank you, Jeff & Julio for the tip. I’m a little ashamed I didn’t know about Wolf’s MoGenerator sooner, but, better late than never!

  4. 4 Chris Hanson

    The reason Xcode will generate (NSNumber *) rather than scalar types for numeric Core Data attributes is primarily that you can make them optional. That means you need a way to distinguish between 0/false and not-present; being nil when not present resolves this.

    If you have a numeric attribute (including a boolean attribute) that’s required, you can just type it as a scalar instead, and Core Data will do the right thing:

    @property (nonatomic) BOOL isDone;

    Even if the attribute is optional, that’ll still work – it’ll just conflate “not present” with “false.”

    One other thing you might want to do is name the property “done” and just specify the getter as “isDone.” That’s the usual Cocoa naming convention:

    @property (nonatomic, getter=isDone) BOOL done;

    Then you can write “if (item.done) { … }” or “item.done = NO;” and the compiler will still generate -isDone for accesses of the property.

  5. 5 am

    Thank you, Chris! I am going to make the naming and the change to the scalar that you’ve suggested. Appreciate the help & insight!

  6. 6 Dalmazio

    Nice, thanks for that. One question though, as of 10.5 we had the Core Data generated primitive accessors which we could declare to suppress compiler-warnings in the interface file. For the equivalent of a declared BOOL value using NSNumber, it looked like:
    @interface MyCustomModel (CoreDataGeneratedPrimitiveAccessors)
    - (NSNumber *) primitiveDone;
    - (void) setPrimitiveDone:(NSNumber *)value;@end:disqus 

    Using scalars directly instead, how would this affect these primitive accessors? Both declared and invoked? And how would we invoke the primitive version of the “done” property?

Leave a Reply