繁体   English   中英

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

[英]Objective-C: Calling selectors with multiple arguments

在 MyClass.m 中,我定义了

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

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

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

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

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

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

  1. 方法的名称(在这种情况下,它将是'myTest')(必需)
  2. 如果方法有输入,则在方法名后面加一个':'(冒号)。
  3. 每个附加输入的名称和“:”。

选择者不知道:

  1. 输入类型
  2. 方法的返回类型。

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

您的方法签名是:

- (void) myTest:(NSString *)

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

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

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

它会工作。

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

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

并致电:

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

@Shane Arney

performSelector:withObject:withObject:

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

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

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

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

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

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

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

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

如果你想了解更多细节,我已经写了一篇文章,包括一个代码示例 重点是线程,但基础仍然适用。

祝好运!

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

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

认为该类应定义为:

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

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

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

一位安卓开发者在 2021_10_15 发帖。

(OC比较难用,-_-||)

使用多个参数调用选择器,

你可以使用NSObject performSelector:withObject:withObject

但只支持传递两个参数!!!

幸运的是,您可以通过objc_msgSend函数实现您的performSelector withObject X 3

#include <objc/message.h>

- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 withObject:(id)object3 {
    typedef id (*send_type)(id, SEL, id, id, id);
    send_type func = (send_type) objc_msgSend;
    id retValue = func(self, aSelector, object1, object2, object3);
    return retValue;
}

用法:

- (NSString *)ObjcMsgSendWithString:(NSString *)string withNum:(NSNumber *)number withArray:(NSArray *)array {
    NSLog(@" ---> %@, %@, %@", string, number, array[0]);
    return @"return 311";
}

- (void)test{
    NSString *str = @"字符串objc_msgSend";
    NSNumber *num = @20;
    NSArray *arr = @[@"数组值1", @"数组值2"];

    SEL sel = @selector(ObjcMsgSendWithString:withNum:withArray:);
    NSLog(@"1223 ---> %@", [self performSelector:sel withObject:str withObject:num withObject:arr]);
}

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM