Uli's Web Site
[ Zathras.de - Uli's Web Site ]
Other Sites: Stories
Pix
Abi 2000
Stargate: Resurgence
Lost? Site Map!
 
 
     home | articles | moose | programming | articles >> blog

 Blog
 
 Blog Topics
 
 Archive
 

15 Most Recent [RSS]

 All you need to know about the Mac keboard
2010-08-09 @488
 
 Review: Sherlock
2010-07-31 @978
 
 Playing with Objective C on Debian
2010-05-08 @456
 
 Fruit vs. Obst
2010-05-08 @439
 
 Mixed-language ambiguity
2010-04-15 @994
 
 Uli's 12:07 AM Law
2010-04-12 @881
 
 Uli's 1:24 AM Law
2010-04-12 @874
 
 Uli's 6:28 AM Law
2010-04-12 @869
 
 Uli's 3:57 PM Law
2010-04-12 @867
 
 Uli's 4:41 PM Law
2010-04-12 @864
 
 Uli's 7:25 AM Law
2010-04-12 @862
 
 Uli's 9:36 PM Law
2010-04-12 @861
 
 Typesafe typecasts
2010-04-12 @471
 
 Porting to the Macintosh
2010-04-09 @592
 
 Uli's source code is on Github!
2010-03-05 @986
 

More...

Safe key-value-coding

Daniel Kennett recently posed the question on Twitter how many of us were defining symbolic constants for use with Key-Value-Coding and Key-Value-Observing. After all, string literals are bad, because they don't get checked by the compiler, so any typo in them goes unnoticed until you realize your key-value-observer method is not called, or you're getting back nil where a property really contains a value.

That immediately sent me musing that it would be nice to have something like @selector() for specifying properties as NSStrings. The nice part about @selector() is that, given you've turned on the Undeclared Selector warning (-Wundeclared-selector), it will complain if given any selector that the compiler doesn't know about yet. Which is usually the case if you make a typo.

Five hours later, the idea suddenly came to me: A property's getter is a selector! And @selector() already does the checking and presents an error message. And one can use NSStringFromSelector() to generate an NSString from any selector. Now, those two are a little wordy, but you can condense that into a neat little macro:

#define PROPERTY(propName)    NSStringFromSelector(@selector(propName))
Admitted, this burns a few additional cycles because it turns a string constant into a function call, but NSStringFromSelector() can probably take an existing string constant from inside the SEL data structure, and you can always take it out of your release builds by writing:
#if DEBUG
#define PROPERTY(propName)    NSStringFromSelector(@selector(propName))
#else
#define PROPERTY(propName)    @#propName
#endif
This turns your property name into the string constant we all know and love in release builds, but does the checking in your debug builds (if you've set up your debug builds with a -DDEBUG=1 flag like many people do).

The advantage of this is that you get checked selectors, even when doing key-value-coding and key-value-observing, without any performance impact on your users. If performance is a problem, you can even only use the checked version of PROPERTY() in a special 'tests' build of your app. But of course then you can still find yourself flummoxed at a missing KVO notification until you do that special build and it complains.

I've added this code to my UKHelperMacros collection of macros, which is available on my source code page.

PS - Thanks to Rob Rix for reminding me of the existence of the # operator, and Jens Ayton for looking up the warning name just when I started wondering why I was getting the warning in one project, but not the other.

Reader Comments: (RSS Feed)
Mike Abdullah writes:
I suppose there is one downside: If you've got a scenario like this: - (BOOL)isEditable; - (void)setEditable:(BOOL)flag; The key is "editable" but there's no @selector(editable) already in existence.
DavidPhillipOster writes:
I couldn't get -Wundeclared-selector to work in a program that also had a few .c files. I filed a bug about it ( http://openradar.appspot.com/7289608 ) . Do you have any suggestions?
Uli Kusterer replies:
Have you tried just checking the "undeclared selectors" checkbox? That will only apply the setting to .m and .mm files, and not to .c files. If you add it to the OTHER_CFLAGS, of course it'll end up in C as well. I do wonder whether there's an OTHER_OBJCFLAGS, though...
Uli Kusterer replies:
Mike, yes, properties with customized getter names are one downside. Also, this won't work for key paths, only for single keys. One could probably create macros that generate a key path, but that would use commas and would have to be a macro like KEYPATH3(foo,bar,baz) instead of just @property(foo.bar.baz).
Ben Cohen writes:
This is useful. Thanks. I wish there was a way to use constants in Interface Builder. I've lost count of the number of times I've had KVO related errors due to miss typing key paths in IB.
Uli Kusterer replies:
Ben, have you filed a bug about this with Apple? I have. Add your voice to the list of people asking for it, it'll increase the likelihood of actually getting it. Besides, it's probably a nice project for an Apple intern.
Comment on this article:
Name:
E-Mail: (not shown, hashed for Gravatar)
Web Site URL: (optional)
Comment: (plain text only)
Please Enter the following word:
Or E-Mail Uli privately.

 
Created: 2009-10-09 @972 Last change: 2010-09-02 @781 | Home | Admin | Edit
© Copyright 2003-2010 by M. Uli Kusterer, all rights reserved.