关于ios:将选择器传递给自定义方法以编程方式创建UIButton

Passing selector to a custom method to create UIButton programmatically

我使用iOS7下的Xcode5做一个简单的项目。当我按下以编程方式创建的按钮时,会出现以下错误:

1
2013-11-10 09:16:02.969 Project2[446:70b] +[KNSunDynamicUIButton buttonSavePressed:]: unrecognized selector sent to class 0x221424

细节:我创建了一个自定义方法,用于以编程方式创建uibutton对象。该自定义方法用于任何视图控制器。该自定义方法需要传入参数,如x、y、width、height、button title和选择器,后者是一个事件处理程序并传入类似"(sel)选择器"。

自定义方法(属于帮助程序类):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+(UIButton*)kNSunSetupWithSelector:(SEL)selector    withX:(int)x y:(int)y width:(int)width height:(int)height
                       buttonTitle:(NSString*)buttonTitle backGroundColor:(CGColorRef) backGroundColor
{

    UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    [button setTitle:@"Save" forState:UIControlStateNormal];
    button.frame = CGRectMake(x, y, width, height);
    button.backgroundColor = [UIColor greenColor];

// selector is used over here
    [button addTarget:self
                    action:selector
          forControlEvents:UIControlEventTouchDown];

    return button;
}

然后在一个view controller.m文件中,我调用这个自定义方法,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-(void)setUpButtons
{
            SEL selector = @selector(buttonSavePressed:);
            _buttonSave = [KNSunDynamicUIButton kNSunSetupWithSelector:selector withX:470 y:410 width:160 height:40 buttonTitle:@"Save" backGroundColor:(_buttonSaveColor)];

            [self.view addSubview:_buttonSave];

}

    @interface MyViewController ()
    {
    ...

        // buttons
        UIButton* _buttonSave;
    }
    @end

按钮事件处理程序在同一个view controller.m文件中的定义如下:

1
2
3
4
- (void)buttonSavePressed:(UIButton*)button
{
    NSLog(@"Button Save clicked.");
}

当我运行代码并点击按钮时,我看到上面提到的异常。请帮忙谢谢。

p.s.如果我将自定义方法重写为在其签名中没有"(sel)selector"参数的替代方法,并让调用该自定义方法的控制器视图执行对选择器进行编码的操作,则没有例外:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-(void)setUpButtons
{
    //Note: the codes are in my view controller .m file

_buttonSave = [KNSunDynamicUIButton kNSunSetupWithX:470 y:410 width:160 height:40 buttonTitle:@"Save" backGroundColor:_buttonSaveColor];


   // Note: selector coding is taken care by codes of my view controller instead of by custom method
   [_buttonSave addTarget:self
    action:@selector(buttonSavePressed:)
    forControlEvents:UIControlEventTouchDown];



    [self.view addSubview:_buttonSave];
    [_buttonSave setupView];
}

以及可选的自定义方法(我不喜欢该方法,因为它不考虑动态传入选择器):

1
2
3
4
5
6
7
8
9
10
11
+(UIButton*)kNSunSetupWithX:(int)x y:(int)y width:(int)width height:(int)height
                   buttonTitle:(NSString*)buttonTitle backGroundColor:(CGColorRef) backGroundColor
{
    UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    [button setTitle:@"Save" forState:UIControlStateNormal];
    button.frame = CGRectMake(x, y, width, height);
    button.backgroundColor = [UIColor greenColor];

    return button;
}

帮助程序类中的行有问题:

1
[button addTarget:self action:selector forControlEvents:UIControlEventTouchDown];

这里,您说助手类将具有您正在通过选择器传递的方法,在您的情况下是buttonSavePressed:方法。

您应该在自己的helper方法中添加in controller参数,以告诉您选择方法放在哪个控制器中。

在您的特定情况下,helper方法应该如下所示(注意,incontroller参数是在selector参数之后添加的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+(UIButton*)kNSunSetupWithSelector:(SEL)selector
                      inController:(UIViewController*)controller
                             withX:(int)x
                                 y:(int)y
                             width:(int)width
                            height:(int)height
                       buttonTitle:(NSString*)buttonTitle
                   backGroundColor:(CGColorRef) backGroundColor
{

UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

[button setTitle:@"Save" forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, width, height);
button.backgroundColor = [UIColor greenColor];

// selector is used over here
[button addTarget:controller
           action:selector
 forControlEvents:UIControlEventTouchDown];

    return button;
}

你应该这样称呼它,从你的控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-(void) setupButtons
{
    SEL selector = @selector(buttonSavePressed:);
    _buttonSaveColor = [UIColor orangeColor].CGColor;
    _buttonSave = [KNSunDynamicUIButton kNSunSetupWithSelector:selector
                                                  inController:self
                                                         withX:470
                                                             y:410
                                                         width:160
                                                        height:40
                                                   buttonTitle:@"Save"
                                               backGroundColor:(_buttonSaveColor)];

    [self.view addSubview:_buttonSave];
}