tags:

views:

73

answers:

2

I have a very simple subclass of UIButton:

@interface MyButton : UIButton
@end

@implementation MyButton

- (id) initWithCoder:(NSCoder *)decoder
{
    if (!(self = [super initWithCoder:decoder]))
        return nil;

    NSLog(@"-[%@ initWithCoder:%@]", self, decoder);

    return self;
}

@end

In Interface Builder I add a UIButton, set its button type to Rounded Rect and its class identity to MyButton.

When running, I have the following log:

-[<MyButton: 0x5b23970; baseClass = UIButton; frame = (103 242; 114 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x5b23a90>> initWithCoder:<UINibDecoder: 0x6819200>]

but the button is not a round rect button anymore.

Observed on both iOS 3.2 and iOS 4.

Is this a bug or am I missing something obvious?

Create an instance of MyButton programmatically is not an acceptable answer, thanks.

A: 

I’m not sure if this is acceptable for your needs, but I tend to prefer to override -awakeFromNib instead of -initWithCoder: in these circumstances. Does doing this resolve the issue you’re seeing?

Rob Rix
+2  A: 

Programmatically, you instantiate a button with +[UIButton buttonWithType:] which is actually a factory that returns a subclass of UIButton. So if you derive from UIButton you actually don't derive from your round rect button class (UIRoundedRectButton) but from a generic button class. But you are not allowed to subclass from UIRoundedRectButton AFAIK since it's an internal class.

It seems to be problematic to derive from UIButton, I've seen a lot of people recommed to derive from UIControl instead and implement the drawing yourself.

But you might find these articles helpful:

http://stackoverflow.com/questions/816024/how-to-override-drawrect-in-uibutton-subclass

http://www.cocoabuilder.com/archive/cocoa/284622-how-to-subclass-uibutton.html

http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/

Also, I don't know why you want to derive from UIButton, but if you want to do some customization that does not involve overwriting any other methods it might be helpful to use the fact that you can do something like this:

- (id)initWithCoder:(NSCoder *)decoder {
   // Decode the frame
   CGRect decodedFrame = ...;
   [self release];
   self = [UIButton buttonWithType:UIButtonTypeRoundedRect];
   [self setFrame:decodedFrame];
   // Do the custom setup to the button
   return self;
}
DarkDust