我正在创建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'
我在这里做错了什么?
答案 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方法。