Friday, April 17, 2009

A “Retain” Trap

I just met a weird problem when using UIButton to create a customized button. The object will be released automatically even I stated a property with retain.

Before I merged this code to my main development version, I tested and run it on a test project and it worked pretty fine.

UIBUtton *myButton;

@property(nonatomic, retain) UIButton *myButton;

then I created this button:

myButton = [UIButton buttonWithType:UIButtonTypeCustom];

and used this button in another method(message):

myButton.frame = …;

When I set the myButton.frame property, it always return “EXC_BAD_ACCESS”, or some weird “Selector is not found on UILayer…” blah blah…

While this snippet worked fine in my test program. After some quick investigation, the problem lies on how we maintain the object after we create it. buttonWithType is a static method for UIButton, so any object created by static method will be added to the auto-release pool, and when this object will be released will be unpredictable. Even we had stated the UIButton as a property which has the retain property, it still need to do the retain by our own hand. Like this:

myButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];

Wow, it works fine now.


  1. If you are using:

    self.myButton = [UIButton buttonWithType:UIButtonTypeCustom];


    [self setMyButton:[UIButton buttonWithType:UIButtonTypeCustom]];

    then system will do the retain for you.

  2. Oh, yes, you are right. If you specified a property and used the "retain" property, the system will do it for you, but if you don't want to expose this variable by property, maybe using manual retain is a necessary choice.

    Later, I found some comments in UICatalog example, the author also used manual retain.