As the title describes I’m looking to add custom properties for every UIViewController and every subclass (like UITableViewController). My first thought was to create a category, but then I realized one cannot add ivars in them, so I can’t synthesize the properties. If I simply subclass UIViewController and add stuff there, It wouldn’t affect other subclasses.
Basically my purpose with this is to add a custom toolbar to my ´UINavigationController´ subclass (No, I can’t use the default for various reasons). It needs to ask each viewController if it wants a toolbar, and – in that case – for an array of toolbarItems. It’s kind of like how the UIToolbar works I believe?
How would you do it?
Adding properties (with backing storage) is possible using Objective-C’s associated object API. I even have a little macro I wrote for the purpose. But before the macro, here’s what it would look like “unrolled”:
You can find the documentation for associated storage here. You should be aware that there is a performance (speed and memory) penalty for using associated objects. They’re a neat trick, but you might want to ask yourself if there’s a better way to do whatever it is you’re trying to do. (The neatest part of the trick, if you ask me, is that the runtime will handle the
-releaseson-deallocfor you, according to the policy you specify; See the docs for more info.)Now here’s the macro:
If you pop that in your header file, then the above example can be reduced to this:
It should go without saying that the policy (i.e. retain/copy/assign, atomic/nonatomic) you declare in the @property declaration needs to match the policy that you use when using the macro (and/or calling the underlying API, if you’re not using the macro) otherwise, you’ll end up leaking memory (or crashing.)
Also, I’ll say it again for emphasis. This trick isn’t “free” so please be sure to measure performance and make sure that whatever benefits you’re getting by using this are worth it.
EDIT: I’m going to backtrack a bit on my emphatic and dire warnings about the performance penalties of associated object storage. There is a penalty, but a quick investigation tells me that properties implemented this way are not all that much worse than their @synthesized and ivar-backed equivalents. The test is a bit contrived, but with 10,000,000 objects, each with 5 associative-storage-backed iVars, I’m seeing ~30% slower performance setting and getting. That’s really not all that dire, IMHO. I was expecting much worse. The time spent doing the memory management (retains, copies) associated with the set operations is dwarfing the overhead from the associative lookups.