objective C:从UIButton类的子类创建的按钮不起作用

时间:2011-06-22 16:57:27

标签: objective-c ios uibutton

我正在创建UIButton的子类,以便创建我自己的自定义按钮。我的代码如下:

//interface file (subclass of uIButton
@interface UICustomButton : UIButton 
{
    Answer *answer;
    NSString *btnType;
}

@property (nonatomic, retain) Answer *answer;
@property (nonatomic, assign) NSString *btnType;

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
- (void)buttonPressed;

@end


//Implementation file (.m)
@implementation UICustomButton
@synthesize answer,btnType;

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        self = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        self.backgroundColor = [UIColor colorWithHexString:@"#E2E4E7"];

    }

    [self addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlStateNormal];

    self.answer = ans;
    self.btnType = type;

    return self;
}

我在使上述代码工作时面临一些问题。我有2个问题

1)按钮没有响应选择器方法“buttonPressed”

2)我遇到了行'self.answer = ans'和'self.btnType = type'堆栈跟踪的运行时错误,如下所示:

-[UIButton setAnswer:]: unrecognized selector sent to instance 0x614ebc0
2011-06-23 00:55:27.038 onethingaday[97355:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setAnswer:]: unrecognized selector sent to instance 0x614ebc0'

我在这里做错了什么?

5 个答案:

答案 0 :(得分:30)

这种情况正在发生,因为当您执行

时,您正在init方法中创建UIButton类型对象而不是UICustomButton类型
self = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];

尝试将init方法替换为

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
{
    self = [self initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
    if (self) 
    {
        self.backgroundColor = [UIColor colorWithHexString:@"#E2E4E7"];

        [self addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];

        self.answer = ans;
        self.btnType = type;
    }

    return self;
}

这会导致self成为UICustomButton类型的对象。

此外,使用addTarget:action:forControlEvents:方法将目标添加到按钮时,您使用了错误的UIControlState参数类型

你应该在下面的那些中使用价值:

  

UIControlEventTouchDown
  UIControlEventTouchDownRepeat
  UIControlEventTouchDragInside
  UIControlEventTouchDragOutside
  UIControlEventTouchDragEnter
  UIControlEventTouchDragExit
  UIControlEventTouchUpInside
  UIControlEventTouchUpOutside
  UIControlEventTouchCancel


编辑: 关于UIButton子类化的说明

网上的很多参考文献都说你不应该继承UIButton类,但不仅有人说过为什么,而且让我深感不安的是UIButton Class Reference根本没有提及任何内容。

如果你以UIWebView Class Reference为例,它明确声明你不应该继承UIWebView

  

Subclassing Notes UIWebView类   不应该是子类。

UIButton的重大关系是它继承自UIControl,而UIControl Class Reference本身就有一个简单明了的解释

  

您可能想要的子类注释   扩展一个UIControl子类   有两个原因:

     
      
  • 观察或修改发送   对目标的动作消息   特别活动
  •   
  • 提供自定义   跟踪行为(例如,到   改变亮点外观)
  •   

所以,这意味着你 CAN UIButton的子类,但是你应该小心你正在做的事情。只需将其子类化即可更改其行为外观。要修改UIButton外观,您应该使用为其提供的接口方法,例如:

  

setTitle:forState:
  setBackgroundImage:forState:
  setImage:forState:

值得一读的参考资料

来源:my post here

答案 1 :(得分:10)

以前不确定这是否在文档中,但无论如何这些都是+ (id)buttonWithType:(UIButtonType)buttonType上的当前注释......

对我而言,只要您使用init而不是buttonWithType,子类化就可以了。不过我还没试过。

  

讨论此方法是用于创建的便利构造函数   具有特定配置的按钮对象。你是UIButton的子类,   此方法不返回子类的实例。如果你想   要创建特定子类的实例,必须分配/ init   直接按钮。

     

创建自定义按钮时 - 即具有该类型的按钮   UIButtonTypeCustom - 按钮的框架设置为(0,0,0,0)   原来。在将按钮添加到界面之前,您应该这样做   将帧更新为更合适的值。

答案 2 :(得分:0)

修改

这个答案可以追溯到几年前,事情已经发生了变化 - 正如Apple文档现在明确提到了子类化并提供了一些提示。

因此,以下答案可能当前发展无关或错误,如果您对当前的技术水平感兴趣,可能会被忽略。


UIButton 意味着要进行子类化。

最好制作一个类别并定义一个工厂方法来提供所需的按钮(正确调用buttonWithType:)。无论如何initWithFrame:都不是初始化按钮的正确方法。

答案 3 :(得分:0)

//
//  BtnClass.m

#import "BtnClass.h"

@implementation BtnClass

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code


    }
    return self;
}

//added custum properities to button
-(id)initWithCoder:(NSCoder *)aDecoder
{
    NSLog(@"initWithCoder");
    self = [super initWithCoder: aDecoder];
    if (self) {
        // Initialization code

        _numberOfItems=[[UILabel alloc]initWithFrame:CGRectMake(40, 8, 160, 30)];
        _numberOfItems.textAlignment=NSTextAlignmentLeft;
        _numberOfItems.font = [UIFont boldSystemFontOfSize:18.0];
        _numberOfItems.textColor = [UIColor darkGrayColor];
        [self addSubview:_numberOfItems];
        _leftImage=[[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 25, 25)];
        [self addSubview:_leftImage];
        _rightImage=[[UIImageView alloc]initWithFrame:CGRectMake(280, 10, 15, 15)];
        [self addSubview:_rightImage];
        [self setImage:[UIImage imageNamed:@"list-bg2-1.png"] forState:UIControlStateNormal];
        [_rightImage setImage:[UIImage imageNamed:@"carat.png"]];
        self.backgroundColor=[UIColor blackColor];


        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"notes-icon.png"]];

        }
        if(self.tag==2)
        {
            [_leftImage setImage:[UIImage imageNamed:@"photos-icon.png"]];

        }
        if(self.tag==3)
        {
            [_leftImage setImage:[UIImage imageNamed:@"videos-icon.png"]];

        }


    }
    return self;
}

//selected method of uibutton
-(void)setSelected:(BOOL)selected
{

    [super setSelected:selected];


    if(selected)
    {
        [self setImage:nil forState:UIControlStateNormal];
        _numberOfItems.textColor = [UIColor whiteColor];

        [_rightImage setImage:[UIImage imageNamed:@"carat-open.png"]];

        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"white-notes-icon.png"]];
        }
        else if(self.tag==2)
        {

            [_leftImage setImage:[UIImage imageNamed:@"white-photo-icon.png"]];

        }
        else
        {
            [_leftImage setImage:[UIImage imageNamed:@"white-video-icon.png"]];

        }

    }
    else{

        _numberOfItems.textColor = [UIColor darkGrayColor];

        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"notes-icon.png"]];

        }
        if(self.tag==2)
        {
            [_leftImage setImage:[UIImage imageNamed:@"photos-icon.png"]];

        }
        if(self.tag==3)
        {
            [_leftImage setImage:[UIImage imageNamed:@"videos-icon.png"]];

        }

        [self setImage:[UIImage imageNamed:@"list-bg2-1.png"] forState:UIControlStateNormal];

        [_rightImage setImage:[UIImage imageNamed:@"carat.png"]];

    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end

答案 4 :(得分:0)

如果您想在用户与按钮交互时收到通知,只需升级UIButton并实施以下方法:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesBegan");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesCancelled");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesMoved");
}

不需要init方法。