performSelector 方法在 Objective-C 中用于在运行时动态调用对象的方法。performSelector 可以传递参数,但其默认情况下最多只支持两个参数。如果需要传递更多参数,可以通过以下几种方式实现:
1. 使用 performSelector:withObject:withObject:...
performSelector:withObject:withObject:... 方法允许传递任意数量的参数,但需要注意的是,这种方法在实际使用中并不常见,且参数必须是对象类型。
示例:
[self performSelector:@selector(testMethod:param2:param3:) withObject:@"param1" withObject:@2 withObject:@3];
- (void)testMethod:(NSString *)param1 param2:(NSNumber *)param2 param3:(NSNumber *)param3 {
NSLog(@"param1: %@, param2: %@, param3: %@", param1, param2, param3);
}
2. 使用 objc_msgSend
objc_msgSend 是 Objective-C 消息机制的核心函数,可以传递任意数量的参数,包括非对象类型的参数。通过 objc_msgSend 可以实现多参数传递。
示例:
#import <objc/message.h>
- (void)viewDidLoad {
[super viewDidLoad];
NSString *param1 = @"111";
NSArray *param2 = @[@2, @3];
NSInteger param3 = 123;
((void (*)(id, SEL, NSString *, NSArray *, NSInteger))objc_msgSend)(self, @selector(testMethod:param2:param3:), param1, param2, param3);
}
- (void)testMethod:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1: %@, param2: %@, param3: %ld", param1, param2, (long)param3);
}
3. 使用 NSInvocation
NSInvocation 是一种更灵活的方式,可以用来封装方法调用,包括方法签名、目标对象、选择器和参数。这种方式适用于需要传递多个参数的情况。
示例:
#import <Foundation/Foundation.h>
- (void)viewDidLoad {
[super viewDidLoad];
SEL selector = @selector(testMethod:param2:param3:);
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
NSString *param1 = @"111";
NSArray *param2 = @[@2, @3];
NSInteger param3 = 123;
[invocation setArgument:¶m1 atIndex:2];
[invocation setArgument:¶m2 atIndex:3];
[invocation setArgument:¶m3 atIndex:4];
[invocation invoke];
}
- (void)testMethod:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1: %@, param2: %@, param3: %ld", param1, param2, (long)param3);
}
4. 封装参数
将多个参数封装成一个对象(如 NSDictionary 或 NSArray),然后通过 performSelector:withObject: 传递。
示例:
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *params = @{@"param1": @"111", @"param2": @[@2, @3], @"param3": @123};
[self performSelector:@selector(testMethodWithParams:) withObject:params];
}
- (void)testMethodWithParams:(NSDictionary *)params {
NSString *param1 = params[@"param1"];
NSArray *param2 = params[@"param2"];
NSInteger param3 = [params[@"param3"] integerValue];
NSLog(@"param1: %@, param2: %@, param3: %ld", param1, param2, (long)param3);
}
总结
performSelector 本身默认只支持传递两个参数,但通过上述方法,可以实现传递多个参数的需求。选择哪种方法取决于具体的应用场景和代码的可读性要求。