Objective-C:使用多个参数调用选择器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1018195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:45:28  来源:igfitidea点击:

Objective-C: Calling selectors with multiple arguments

objective-cselector

提问by Stu

In MyClass.m, I've defined

在 MyClass.m 中,我定义了

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

and the appropriate declaration in MyClass.h . Later I want to call

以及 MyClass.h 中的适当声明。后来我想打电话

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

in MyClass.m but I get an error similar to * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*-[MyClass myTest:withAtring:]: unrecognized selector sent to instance 0xe421f0'

在 MyClass.m 中,但我收到类似于* 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序的错误 ,原因:“*-[MyClass myTest:withAtring:]: unrecognized selector sent to instance 0xe421f0”

I tried a simpler case with a selector that took no arguments that printed a string to console and that worked just fine. What's wrong with the code and how can I fix it? Thanks.

我尝试了一个更简单的案例,使用一个选择器,它不带任何参数,将字符串打印到控制台,并且工作得很好。代码有什么问题,我该如何解决?谢谢。

采纳答案by Lyndsey Ferguson

Your method signature is:

您的方法签名是:

- (void) myTest:(NSString *)

withAString happens to be the parameter (the name is misleading, it looks like it is part of the selector's signature).

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

If you call the function in this manner:

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

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

It will work.

它会起作用。

But, as the other posters have suggested, you may want to rename the method:

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

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

And call:

并调用:

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

回答by Shane Arney

In Objective-C, a selector's signature consists of:

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

  1. The name of the method (in this case it would be 'myTest') (required)
  2. A ':' (colon) following the method name if the method has an input.
  3. A name and ':' for every additional input.
  1. 方法的名称(在本例中为“myTest”)(必填)
  2. 如果方法有输入,则在方法名称后跟一个“:”(冒号)。
  3. 每个附加输入的名称和“:”。

Selectors have no knowledge of:

选择器不知道:

  1. The input types
  2. The method's return type.
  1. 输入类型
  2. 方法的返回类型。

Here's a class implementation where performMethodsViaSelectors method performs the other class methods by way of selectors:

这是一个类实现,其中 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

The method you want to create a selector for has a single input, so you would create a selector for it like so:

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

SEL myTestSelector = @selector(myTest:);

回答by Lirik

@Shane Arney

@沙恩阿尼

performSelector:withObject:withObject:

You might also want to mention that this method is only for passing maximum 2 arguments, and it cannot be delayed. (such as performSelector:withObject:afterDelay:).

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

kinda weird that apple only supports 2 objects to be send and didnt make it more generic.

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

回答by Zack

Your code has two problems. One was identified and answered, but the other wasn't. The first was that your selector was missing the name of its parameter. However, even when you fix that, the line will still raise an exception, assuming your revised method signature still includes more than one argument. Let's say your revised method is declared as:

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

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

Creating selectors for methods that take multiple arguments is perfectly valid (e.g. @selector(myTestWithString:comparedTo:) ). However, the performSelector method only allows you to pass one value to myTest, which unfortunately has more than one parameter. It will error out and tell you that you didn't supply enough values.

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

You could always redefine your method to take a collection as it's only parameter:

你总是可以重新定义你的方法来获取一个集合,因为它是唯一的参数:

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

However, there is a more elegant solution (that doesn't require refactoring). The answer is to use NSInvocation, along with its setArgument:atIndex:and invokemethods.

但是,有一个更优雅的解决方案(不需要重构)。答案是使用NSInvocation的,与它一起setArgument:atIndex:invoke方法。

I've written up an article, including a code example, if you want more details. The focus is on threading, but the basics still apply.

如果您想了解更多详细信息,我已经写了一篇文章,其中包括一个代码示例。重点是线程,但基础知识仍然适用。

Good luck!

祝你好运!

回答by Rob Napier

Your method signature makes no sense, are you sure it isn't a typo? I'm not clear how it's even compiling, though perhaps you're getting warnings that you're ignoring?

您的方法签名毫无意义,您确定这不是打字错误吗?我不清楚它是如何编译的,尽管您可能会收到您忽略的警告?

How many parameters do you expect this method to take?

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

回答by Grouchal

Think the class should be defined as:

认为该类应定义为:

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

You only have a single parameter so you should only have a single :

你只有一个参数,所以你应该只有一个:

You might want to consider using %@ in your NSLog also - it is just a good habit to get into - will then write out any object - not just strings.

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

回答by Kannan Prasad

iOS users also expect autocapitalization: In a standard text field, the first letter of a sentence in a case-sensitive language is automatically capitalized.

You can decide whether or not to implement such features; there is no dedicated API for any of the features just listed, so providing them is a competitive advantage.

iOS 用户还希望自动大写:在标准文本字段中,区分大小写语言的句子的第一个字母会自动大写。

您可以决定是否实现这些功能;上面列出的任何功能都没有专用的 API,因此提供它们是一种竞争优势。

Apple document is saying there is no API available for this feature and some other expected feature in a customkeyboard. so you need to find out your own logic to implement this.

Apple 文档说没有可用于此功能和自定义键盘中的其他一些预期功能的 API。所以你需要找出自己的逻辑来实现这一点。