Objective-C:调用具有多个参数的选择器

时间:2009-06-19 14:19:47

标签: objective-c selector

在MyClass.m中,我定义了

- (void) myTest: (NSString *) withAString{
    NSLog(@"hi, %@", withAString);
}

和MyClass.h中的相应声明。后来我想打电话给

[self performSelector:@selector(mytest:withAString:) withObject: mystring];

在MyClass.m中,但我收到类似的错误 *由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'* - [MyClass myTest:withAtring:]:无法识别的选择器发送到实例0xe421f0'

我尝试了一个更简单的情况,它带有一个没有参数的选择器,它将一个字符串打印到控制台,并且工作正常。代码有什么问题,我该如何解决?感谢。

7 个答案:

答案 0 :(得分:307)

在Objective-C中,选择器的签名包括:

  1. 方法的名称(在这种情况下,它将是'myTest')(必填)
  2. 如果方法有输入,则在方法名后跟一个':'(冒号)。
  3. 每个额外输入的名称和“:”。
  4. 选择者不知道:

    1. 输入类型
    2. 方法的返回类型。
    3. 这是一个类实现,其中performMethodsViaSelectors方法通过选择器执行其他类方法:

      @implementation ClassForSelectors
      - (void) fooNoInputs {
          NSLog(@"Does nothing");
      }
      - (void) fooOneIput:(NSString*) first {
          NSLog(@"Logs %@", first);
      }
      - (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second {
          NSLog(@"Logs %@ then %@", first, second);
      }
      - (void) performMethodsViaSelectors {
          [self performSelector:@selector(fooNoInputs)];
          [self performSelector:@selector(fooOneInput:) withObject:@"first"];
          [self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second"];
      }
      @end
      

      您要为其创建选择器的方法有一个输入,因此您可以为它创建一个选择器:

      SEL myTestSelector = @selector(myTest:);
      

答案 1 :(得分:134)

您的方法签名是:

- (void) myTest:(NSString *)

withAString恰好是参数(名称具有误导性,看起来它是选择器签名的一部分)。

如果以这种方式调用该函数:

[self performSelector:@selector(myTest:) withObject:myString];

它会起作用。

但是,正如其他海报所建议的那样,您可能想要重命名该方法:

- (void)myTestWithAString:(NSString*)aString;

并致电:

[self performSelector:@selector(myTestWithAString:) withObject:myString];

答案 2 :(得分:13)

@Shane Arney

performSelector:withObject:withObject:

您可能还想提一下,此方法仅用于传递最多2个参数,并且不能延迟。 (例如performSelector:withObject:afterDelay:)

有点奇怪的是,苹果只支持发送2个对象并且没有使它更通用。

答案 3 :(得分:7)

您的代码有两个问题。一个被确认并回答,但另一个没有。第一个是你的选择器缺少其参数的名称。但是,即使您修复了该行,该行仍将引发异常,假设您修改的方法签名仍包含多个参数。假设您修改后的方法声明为:

-(void)myTestWithString:(NSString *)sourceString comparedTo:(NSString *)testString ;

为采用多个参数的方法创建选择器是完全有效的(例如@selector(myTestWithString:comparisonTo :))。但是,performSelector方法只允许您将一个值传递给myTest,不幸的是,myTest有多个参数。它会报错并告诉您没有提供足够的值。

您可以随时重新定义您的方法以获取集合,因为它是唯一的参数:

-(void)myTestWithObjects:(NSDictionary *)testObjects ;

然而,有一个更优雅的解决方案(不需要重构)。答案是使用NSInvocation及其setArgument:atIndex:invoke方法。

如果您需要更多详细信息,我已经写了an article, including a code example。重点是线程,但基础知识仍然适用。

祝你好运!

答案 4 :(得分:3)

你的方法签名毫无意义,你确定它不是拼写错误吗?我不清楚它是如何编译的,虽然你可能会收到警告你忽略了?

您希望此方法采用多少个参数?

答案 5 :(得分:2)

认为课程应该定义为:

- (void) myTestWithSomeString:(NSString *) astring{
    NSLog(@"hi, %s", astring);
}

您只有一个参数,因此您应该只有一个参数:

您可能也想考虑在NSLog中使用%@ - 这只是一个很好的习惯 - 然后写出任何对象 - 而不仅仅是字符串。

答案 6 :(得分:0)

  

iOS用户也期望自动资本化:在标准文本字段中,   案例敏感语言中句子的第一个字母是   自动大写。

     

您可以决定是否实施此类功能;没有   针对刚刚列出的任何功能的专用API,因此提供它们   是一种竞争优势。

Apple文档称,此功能没有可用的API以及自定义键盘中的其他预期功能。所以你需要找出自己的逻辑来实现它。