如何为作为参数传入的Objective-C选择器添加参数?
解决带参数选择器作为方法参数的调用问题
首先,你原来的executeSelector:fromObject:方法只处理了无参选择器,要支持带参数的情况,有两种简洁的实现方式:
方式一:适配有限参数个数(适合固定参数数量场景)
直接修改executeSelector方法,增加一个参数数组来接收要传递的参数,内部根据参数个数调用对应的performSelector方法:
- (void)executeSelector:(SEL)func fromObject:(id)object withArgs:(NSArray*)args { if (!func || !object) return; switch (args.count) { case 0: [object performSelector:func]; break; case 1: [object performSelector:func withObject:args.firstObject]; break; case 2: [object performSelector:func withObject:args[0] withObject:args[1]]; break; // 更多参数的话,这种方式就不够用了,建议用下面的NSInvocation方案 } }
调用的时候直接把参数打包成数组传入,非常简洁:
- (void)runSelector { NSString* string1 = @"Hello "; NSString* string2 = @"World"; [self executeSelector:@selector(testWithInput:andInput:) fromObject:self withArgs:@[string1, string2]]; }
方式二:用NSInvocation实现通用参数支持(任意参数个数都能处理)
如果需要支持任意数量的参数,NSInvocation是更通用的方案,不需要为不同参数个数写分支:
- (void)executeSelector:(SEL)func fromObject:(id)object withArguments:(NSArray*)arguments { if (!func || !object) return; // 获取方法签名,检查选择器是否存在 NSMethodSignature* signature = [object methodSignatureForSelector:func]; if (!signature) { NSLog(@"Selector %@ not found on object %@", NSStringFromSelector(func), object); return; } NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.target = object; invocation.selector = func; // 注意:NSInvocation的前两个参数是self和_cmd,所以参数从索引2开始设置 for (NSInteger i = 0; i < arguments.count; i++) { id arg = arguments[i]; if ([arg isKindOfClass:[NSObject class]]) { [invocation setArgument:&arg atIndex:i + 2]; } // 如果需要支持基本数据类型(如int、float),需要额外处理,这里只针对NSObject子类 } [invocation invoke]; }
调用方式和上面一致:
[self executeSelector:@selector(testWithInput:andInput:) fromObject:self withArguments:@[string1, string2]];
为什么这种方式更简洁?
你不用为每个参数个数单独写重载方法,只需要把所有参数打包成一个数组传入即可,不管选择器需要1个、2个还是更多参数,这个方法都能处理。
内容的提问来源于stack exchange,提问作者headbanger
相关产品推荐
相关产品推荐

