You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为作为参数传入的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:10:40