如题如何使用performSelector传递两个以上参数以及如何传递结构体
分两个问题:
1.如何传递两个以上参数
2.如何传递结构体
1 如何传递两个以上参数
有四种方式可以实现
1.将所有参数放入一个字典/数组传过去
2.使用objc_msgSend()传递
3.用NSInvocation传递
4.利用runtime特性传递
a 将所有参数放入一个字典/数组传过去
思路:这种方式就是将所有参数都放到一个字典/数组中,然后将数组/字典当作一个参数传给要调用的方法。
注意点:这种方式需要改动要调用的方法的取参数的方式,比如使用字典传递,双方约定每一个参数放入字典对应的key是什么,在方法哪部才能从对应的key中取出参数值。
具体代码如下:
//封装参数
NSDictionary *dic = @{@"param1":@"this is a string",@"param2":@[@2,@3,@3],@"param3":@123};
//调用方法
[self performSelector:@selector(testFunctionWithParams:) withObject:dic];
- (void)testFunctionWithParams:(NSDictionary *)paramDic {
NSLog(@"%s dic:%@",__FUNCTION__, paramDic);
}
b 使用objc_msgSend()传递
思路:利用objc_msgSend() 方法可以传递多个参数的特性调用方法执行
具体代码如下:
((void (*)(id,SEL,NSString *, NSArray *, NSInteger))objc_msgSend)(self, @selector(textFunctionWithParam:param2:param3:),@"111",@[@2,@3],123);
//有三个参数的方法
-(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}
c 用NSInvocation传递
思路:将方法调用采用NSInvocation调用,NSInvocation 不限制参数数量
这里可以了解一下NSInvocation的用法https://www.jianshu.com/p/e24b3420f1b4
具体代码如下:
//可以传多个参数的方法
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects
{
// 方法签名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
if (signature == nil) {
//可以抛出异常也可以不操作。
}
// NSInvocation : 利用一个NSInvocation对象包装一次方法调用(方法调用者、方法名、方法参数、方法返回值)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
// 设置参数
NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd以外的参数个数
paramsCount = MIN(paramsCount, objects.count);
for (NSInteger i = 0; i < paramsCount; i++) {
id object = objects[i];
if ([object isKindOfClass:[NSNull class]]) continue;
[invocation setArgument:&object atIndex:i + 2];
}
// 调用方法
[invocation invoke];
// 获取返回值
id returnValue = nil;
if (signature.methodReturnLength) { // 有返回值类型,才去获得返回值
[invocation getReturnValue:&returnValue];
}
return returnValue;
}
//调用方法
NSArray *paramArray = @[@"112",@[@2,@13],@12];
[self performSelector:@selector(textFunctionWithParam:param2:param3:) withObjects:paramArray];
//要调用的方法
-(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}
2 如何传递结构体
思路:将结构体封装成NSValue对象
关于NSValue的更多内容请参照:http://nshipster.cn/nsvalue/
typedef struct TTTestStrout{
int aaa;
int bbb;
} testStrout;
//传结构体
testStrout testS = {10000, 1234};
NSValue *value = [NSValue valueWithBytes:&testS objCType:@encode(testStrout)];
//dic
NSDictionary *dataDic = @{@"param1":@"ssfs",@"param2":@[@333,@32343],@"param3":value};
[self performSelector:@selector(testFunctionWithParams:) withObject:dataDic];
- (void)testFunctionWithParams:(NSDictionary *)paramDic {
NSLog(@"%s dic:%@",__FUNCTION__, paramDic);
NSValue *paramValue = paramDic[@"param3"];
testStrout paramStrout;
[paramValue getValue:¶mStrout];
NSLog(@"%d",paramStrout.aaa);
}
网友评论