Mistakes I Made Using Bindings Without Core Data

Key-Value Coding is part of the magic behind Cocoa’s bindings. Up until yesterday I had only been binding to an ObjectController or to an ArrayController backed by Core Data. This is very powerful, but bindings pre-date Core Data so clearly not a necessity. So yesterday I went to bind an NSProgressIndicator’s ‘isIndeteriminate’ to a BOOL. Two gotchas that I ran into that I can see myself running into again:

1) update 6.7.06: there is no #1 – I just had this blatantly wrong – see comments. Thanks Jean-Francois.

<

p> Binding to a BOOL requires the result to be returned in an NSNumber. My isIndeterminate method, although backed by a simple BOOL, needed to be

- (NSNumber ) isIndeterminate
{
return [NSNumber numberWithBool:isIndeterminate];
}
2) Bindings require you to notify them when you change the value (see, it’s not *all magic). So setIsIndeterminate looks like this:
- (void)setIsIndeteriminate:(NSNumber *)flag
{
[self willChangeValueForKey:@“isIndeteriminate”];
isIndeteriminate = [flag boolValue];
[self didChangeValueForKey:@“isIndeteriminate”];
}
Without this, changing the isIndeterminate member variable would have no effect.

Some other goodies:

  • Accessorizer can create your accessor methods for you. This is a great tool that greatly speeds up a tedious task.
  • Coredata MenuCore Data can generate similar code for you. Go to your data model and right click on an entities attribute. You should see a “Copy Method Declarations to Clipboard” and a “Copy Method Implementations to Clipboard”. Core Data doesn’t need you to generate these. If you use the setValue:foo forKey:@“bar” syntax the correct things happen. However, it’s often nice to just say [obj setBar:foo];

5 Responses to “Mistakes I Made Using Bindings Without Core Data”

  1. Jean-Francois Roy Says:

    This problem is stange to me, because the KVC documentation clearly states in http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/DataTypes.html that KVC will automatically wrap and unwrap BOOL as an NSNumber.

  2. BrianC Says:

    Thanks Jean-Fancois. I’ve updated the post to point out that I was just wrong on that one (which is good).

  3. Marcus S. Zarra Says:

    Going to have to disagree with you on number 2. I have never had to call willChange and didChange inside of a set method.

    In fact, if you want some more magic instead, remove the getter and setter completely! Try this at home…

    In your interface:

    BOOL isIndeteriminate;

    When you want to change this value:

    [self setValue:[NSNumber numberWithBool:YES] forKey:@”isIndeteriminate”];

    It will update the value AND notify any listeners that the value has changed. To read the value call:

    [[self valueForKey:@"isIndeteriminate"] boolValue];

    Note: valueForKey is what IB uses to look up this value.

    There is no need (at least in Tiger, have not messed with 10.3 in a while) for simple getters and setters.

    Even without using these methods, there should be no reason to use willChange and didChange in your setter. The setter handles the notification for you “automagically”.

    Marcus S. Zarra Zarra Studios LLC http://www.zarrastudios.com Simply Elegant Software for OS X

  4. BrianC Says:

    Marcus, thanks for the comment. I actually like the getters and setters. I’m not a fan of the ’setValue:forKey:’ stuff. I like seeing [self setIsIndeterminate:YES/NO] instead of the setValue:forKey stuff. I think the getters and setters read better and in most cases are worth their effort.

  5. jobi Says:

    The reason you have to use the workaround in 2) is that “setIsIndeteriminate:” is not the proper accessor for a value named “indeterminate”. From the KVC system’s perspective, you are modifying indeterminate without warning (unless you call will/didChange). The proper name would have been “setIndeterminate:”; i.e. the value being set is “indeterminate”, not “isIndeterminate”.

    If you try to use setValue:forKey:, you’ll probably see that your setter method won’t be called (even though the variable will change, since in that case KVC just goes and muddles with your object directly).

Leave a Reply


© 2006-2009 roobasoft, LLC