Xcode's generated IBOutlet code is not always what you want

Showing 1-1 of 1 messages
Xcode's generated IBOutlet code is not always what you want janine 3/9/11 3:42 PM
Last night a bunch of us got into a discussion of the code generated by Xcode 4 when you make a drag-n-drop connection from IB (this was a followup to the question I posted yesterday).  I learned some things I didn't know, and even though most of you are not using Xcode 4 (or shouldn't be :), I thought the concepts were useful enough to be worth passing on.

The issue was the code that Xcode 4 inserts into your project when you create an outlet by dragging from your object in IB to anywhere outside the interface block in the corresponding header (.h) file.  It adds an ivar and a @property declaration to the header:

UIButton *test3button;

and

@property (nonatomicretainIBOutlet UIButton *test3button;

and a @synthesize to the implementation (.m) file.  

@synthesize test3button;

It also adds the following code to handle deallocation:

viewDidUnload

[self setTest3button:nil];

dealloc

[test3button release];

The primary issue here (and the only one you need to pay attention to if you're new at this) is that this code can have unintended side-effects if you have a customized setter.  It is safest all around to replace that line in viewDidUnload with these two:

setTest3button = nil;
[test3button release];

(you can leave the line in dealloc alone)

It's also worth noting that if you do the drop within the interface block, Xcode 4 will create an old-style ivar without a @property, which is generally not what you want.

Because Xcode 4 is handling the most general case, there are a couple of other issues that the more advanced programmer should be aware of:

1. Best practice would be to only have the @property in the header file if you want the ivar to be accessible from outside the class.  For an IBOutlet this is often not the case.  There's no major harm to doing it Xcode's way, but it is more correct to have an additional interface block inside the implementation file and put your private @property statements there.

2. Some people go even further and leave out the ivar definition that Xcode 4 puts in the header's interface block.  The @property statement is sufficient and the ivar will be generated for you from it.  If you've found yourself copying and pasting the ivar definition to make the @property, and been annoyed by it, you'll appreciate this I'm sure.  There's a drawback, though - ivars generated by Xcode aren't visible in the debugger, so you need to either print them manually (po [self foo]) or add the ivar declaration to any that you find yourself needing access to while debugging.