【问题标题】:selector as parameter in IOS选择器作为IOS中的参数
【发布时间】:2025-12-15 14:20:16
【问题描述】:

我想为每个创建的按钮提出不同的方法。 我尝试在 viewDidLoad 中调用“FirstImage”方法,但它不起作用。

ViewDidLoad 中的选择器有问题。无法识别“FirstImage”,这是一个没有参数的 void 方法。

ViewController.m

- (void)createFirstButton:(NSString *)myName: (SEL *)myAction{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn        addTarget:self
                action:@selector(myAction)
                forControlEvents:UIControlEventTouchUpInside];
    [btn setTitle:myName forState:UIControlStateNormal];
    btn.frame = CGRectMake(20, 916, 120, 68);
    [self.view addSubview:btn];
}

- (void)viewDidLoad{
    [self createFirstButton:@"First" myAction:[self FirstImage]];
}

我做了什么(我把“CreateFirstButton”改成了“CreateButton”):

ViewControler.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize myHeight;
@synthesize myWidth;
@synthesize myX;
@synthesize myY;

- (void)createButton:(NSString *)myName:(SEL)myAction:(NSUInteger)my_x:(NSUInteger)my_y:(NSUInteger)my_width:(NSUInteger)my_height
{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn    addTarget:self
            action:myAction
            forControlEvents:UIControlEventTouchUpInside];
    [btn setTitle:myName forState:UIControlStateNormal];
    btn.frame = CGRectMake(my_x, my_y, my_width, my_height);
    [self.view addSubview:btn];
}

- (void)myXcrementation{
    myX = myX + 150; 
}

- (void)viewDidLoad{
    myX = 20; myY = 916; myWidth = 120; myHeight = 68;
    [self createButton:@"First":@selector(FirstImage):myX:myY:myWidth:myHeight];
    [self myXcrementation];
    [self createButton:@"Previous":@selector(PreviousImage):myX:myY:myWidth:myHeight];
    [self myXcrementation];
    [self createButton:@"Pause":@selector(PauseImage):myX:myY:myWidth:myHeight];
    [self myXcrementation];
    [self createButton:@"Next":@selector(NextImage):myX:myY:myWidth:myHeight];
    [self myXcrementation];
    [self createButton:@"Last":@selector(LastImage):myX:myY:myWidth:myHeight];
}

- (void)FirstImage{
    current = 0;
    [self SetImage];
}

-(void)SetImage{
    [myImageView setImage: [myArray objectAtIndex:(current)]];
}

@end

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController{
}

@property(assign, nonatomic) NSUInteger myHeight;
@property(assign, nonatomic) NSUInteger myWidth;
@property(assign, nonatomic) NSUInteger myX;
@property(assign, nonatomic) NSUInteger myY;

@end 

我再次编辑了这篇文章,没有更多错误。 特别感谢大家。我花了一些时间才明白:)

【问题讨论】:

  • 我想知道所有按钮都有相同的框架?
  • 它也会与Unrecognized selector 一起崩溃,因为您正在实施的消息称为createFirstButton:: 而不是createFirstButton:myAction:。此外,您不需要SEL *(类似于id):SEL 就足够了。此外,@selector(myAction) 并没有按照你的想法做,只需使用 myAction 代替它。

标签: ios selector


【解决方案1】:

你必须使用@selector如下

[self createFirstButton:@"First" myAction:@selector(FirstImage)];

那么你的签名是错误的,因为SEL 不应该是一个指针。

改变

- (void)createFirstButton:(NSString *)myName: (SEL *)myAction{

- (void)createFirstButton:(NSString *)myName: (SEL)myAction{

最后myActionSEL 类型所以你可以直接将它传递给UIButton 方法,如下

[btn addTarget:self
     action:myAction
     forControlEvents:UIControlEventTouchUpInside];

另外,我想补充一点,对方法使用大写名称是一种非常糟糕的做法。

【讨论】:

  • 对不起,我是 iOS 新手,我犯了太多错误。我试着纠正它。
  • 别抱歉,在使用新的语言/框架时犯错是完全可以的;)修复我指出的所有内容,你应该会没事的。
  • 如果 FirstImage 方法有参数,这将不起作用。例如,我们可能想要识别请求来自的按钮,例如该方法的发送者 ID。任何想法如何改变它以适应带有参数的方法?
  • 在方法名中,为什么冒号和变量名是对着的?这是一个复杂的方法名称,冒号需要在它的参数旁边。 myName 和冒号之间应该有一个空格,冒号和 (SEL *)myAction 之间应该没有空格。这很重要,因为冒号与它左边的数据无关,而与它右边的数据有关。
  • @AlexZavatone,只是从 OP 的问题中复制粘贴,我没有费心去改变它,因为这不是重点。随意编辑
【解决方案2】:

你应该使用

- (void)viewDidLoad{
    [self createFirstButton:@"First" myAction:@selector(FirstImage)];
}

- (void)viewDidLoad{
    [self createFirstButton:@"First" myAction:NSSelectorFromString(@"FirstImage")];
}

@selector(myAction) 应替换为myAction(SEL *) 应替换为SEL

在您的代码中,在调用 -createFirstButton:myAction: 之前,将首先评估(调用)它的第二个参数 [self FirstImage]。 @selector() 接受一个名称并返回一个 SEL。

【讨论】:

  • 感谢您的帮助,但我仍然收到此消息:“ViewController”没有可见的@interface 声明选择器“createFirstButton:myAction:”
  • @icewall0,你应该在它的头文件中声明- (void)createFirstButton:(NSString *)myName myAction:(SEL)myAction;@interface ViewController@end之间,如果它应该被暴露为一个公共方法或者在@interface ViewController()@end之前@987654334之前@ 作为私有方法。
【解决方案3】:

如下改变方法字面量

- (void)createFirstButton: (NSString *)myName withAction: (SEL)myAction

对于声明和定义。

还有你为什么要声明一个公共的和私有的一样的方法?

【讨论】:

  • 构建成功,但是当我按下我的 FirstButton 时我仍然崩溃。我在这段代码上工作了太多我累了抱歉
  • 在崩溃时按下按钮后,您在日志中收到什么消息?
【解决方案4】:

使用

[self createFirstButton:@"First" withAction:NSSelectorFromString(@"FirstImage")];

并将方法名称更改为:

- (void)createFirstButton:(NSString *)myName: withAction: (SEL) myAction{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn        addTarget:self
                action:myAction
                forControlEvents:UIControlEventTouchUpInside];
    [btn setTitle:myName forState:UIControlStateNormal];
    btn.frame = CGRectMake(20, 916, 120, 68);
    [self.view addSubview:btn];
}

还有,

我想知道所有按钮都有相同的框架,如果可能的话通过frame这个方法。

【讨论】:

  • 我打算用变量作为框架
  • @icewall0 : 我应该提一下你是怎么做到的吗?
【解决方案5】:

如果您希望将字符串作为方法名称传递给选择器,请使用 NSSelectorFromString。字符串应以 ':' 结尾示例-

    NSString *myName=@"aMethod:"; 
    [button addTarget:self 
               action:NSSelectorFromString(myName)
     forControlEvents:UIControlEventTouchDown];

【讨论】: