UIButtonTypeDetailDisclosure:发送到实例的无法识别的选择器

时间:2013-02-11 22:43:49

标签: ios cocoa-touch uibutton unrecognized-selector

我有一个自定义按钮类:

CustomButton.h文件:

@interface CustomButton : UIButton
@property (nonatomic, retain) NSString* info;
@end

CustomButton.m文件:

#import "CustomButton.h"

@implementation CustomButton

@synthesize info;

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

@end

在我的主视图控制器中:

CustomButton* btn = [CustomButton buttonWithType:UIButtonTypeDetailDisclosure];

[btn setInfo:@"foobar"];
NSLog(@"%@", [btn info]);

[self.view addSubview:btn];

如果它只是一个简单的按钮([CustomButton new]),我不会收到任何错误。但如果我选择buttonWithType:UIButtonTypeDetailDisclosure,我会收到此错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '-[UIButton setInfo:]: unrecognized selector sent to instance 0x753c8c0'

为什么会这样?

2 个答案:

答案 0 :(得分:1)

您呼叫的buttonWithType:方法来自UIButton,而不是CustomButton课程。 buttonWithType:的返回值为UIButton。即使您将其分配给CustomButton类型的变量,它仍然是UIButton对象。由于UIButton没有info属性或setInfo:方法,因此您会收到错误。

答案 1 :(得分:1)

只要UIButton未提供initWithType:方法,您就无法继承“键入”按钮。您也无法为库类创建extension。 将某些内容“附加”到预定义对象的唯一方法是使用associated objects

#import <objc/runtime.h>

UIButton* btn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
NSString* info = @"foobar";
objc_setAssociatedObject(btn, "info", info, OBJC_ASSOCIATION_RETAIN);
//Later somewhere
NSString* btnInfo = (NSString*)objc_getAssociatedObject(btn, "info");

“info”可以是您喜欢的任何字符串,它只是稍后检索该对象的键。 OBJC_ASSOCIATION_RETAIN表示在调用btn对象的dealloc:之后,对象将被保留并自动释放。您可以找到有关here的更多详细信息。

解决问题的另一种方法是继承UIButton,添加您的信息属性,并通过使用setImage:forState:方法设置自定义图片使其看起来像公开按钮。

通常,将某些数据与标准UI控件耦合是架构不良的标志。也许你会向后退一步并尝试找到一些其他方法来传递你需要使用它的字符串?