0

I have a UIViewController class in which im trying to allocate a UIButton Class. Here is a sample code.

MyViewController.m 
- (void)viewDidLoad
{
CGRect frame = CGRectMake(companybuttonxOffset, companybuttonyOffset, buttonWidth, buttonHeight);
CustomButton *customButton = [[CustomButton alloc]initWithFrame:frame];
[self.view addSubview:customButton];
[super viewDidLoad];
}
CustomButton.h

#import <UIKit/UIKit.h>

@interface CustomButton : UIButton {
}
@property (nonatomic, assign) NSInteger toggle;
- (void)buttonPressed: (id)sender;
@end


CustomButton.m

#import "CustomButton.h"

@implementation CustomButton
@synthesize toggle;
- (id) initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
//custom button code
[self addTarget: self action: @selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];

}
return self;
}
- (void)buttonPressed: (id)sender
{
    NSLog(@"buttonPressed !!!!!");
}
@end

Although the button is present in my viewcontroller, if i press the button, i keep getting this error - -[UIButton buttonPressed:]: unrecognized selector sent to instance 0xb1dca50

From what i understand after searching for a lot for an answer is that, initWithFrame never gets called when you subclass the button in IB. Instead i should use initWithCoder. Is this right ? If this is it, then i have no idea what NSCoder is, and how i can use it.
Im tired of searching for a solution for this, please help me out guys.

  • 1
    Are you doing something in IB? You're creating this button in code, so initWithFrame: should be called -- just put a log in there to test. I think the bigger problem though, is that the buttonPressed: method should be in your view controller not in the button code -- that's standard MVC design. – rdelmar Sep 28 '12 at 17:25
  • @Farhan were you able to resolve this issue? Anything I can explain more about my answer? – Carl Veazey Sep 30 '12 at 06:39

2 Answers2

0

I guess that in the IB, you have not changed your button's class to CustomButton. Therefore, it is still a UIButton.

Nonetheless, I back rdelmar here that this is not a very good design. Your view controller should handle the event, not the button itself.

BiGGA
  • 358
  • 2
  • 5
0

While I agree you should usually have all targets be in the controller layer, give this a try:

- (id)initWithCoder:(NSCoder *)coder
{
    if (self = [super initWithCoder:coder])
    {
        [self customButtonInit];
    }

    return self;
}


- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        [self customButtonInit];
    }

    return self;
}


- (void)customButtonInit
{
    [self addTarget: self action: @selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
}
Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
  • thank you so much, although i have a doubt, how do i initialise the button class inside the view controller if im going to use init with code, is it same as - CustomButton *customButton = [[CustomButton alloc]initWithFrame:frame]; or is there anything else ? – Farhan.iOSDeveloper Oct 02 '12 at 18:16
  • @Farhan.iOSDeveloper You're not going to want to call `initWithCoder:` directly - that's called when you get your button out of the nib. That is, if you make a button in a nib / storyboard, and set its class to be your `CustomButton`, that's when `initWithCoder:` will be called. So you only need to worry about calling that when you are loading a view from a nib or storyboard. You only have to implement the method, as shown. And then assign the class in interface builder. Does that answer your question? – Carl Veazey Oct 02 '12 at 18:24