如題如何使用performSelector傳遞兩個以上參數(shù)以及如何傳遞結(jié)構(gòu)體
分兩個問題:
1.如何傳遞兩個以上參數(shù)
2.如何傳遞結(jié)構(gòu)體
1 如何傳遞兩個以上參數(shù)
有四種方式可以實現(xiàn)
1.將所有參數(shù)放入一個字典/數(shù)組傳過去
2.使用objc_msgSend()傳遞
3.用NSInvocation傳遞
4.利用runtime特性傳遞
a 將所有參數(shù)放入一個字典/數(shù)組傳過去
思路:這種方式就是將所有參數(shù)都放到一個字典/數(shù)組中衫哥,然后將數(shù)組/字典當(dāng)作一個參數(shù)傳給要調(diào)用的方法茎刚。
注意點:這種方式需要改動要調(diào)用的方法的取參數(shù)的方式,比如使用字典傳遞撤逢,雙方約定每一個參數(shù)放入字典對應(yīng)的key是什么膛锭,在方法哪部才能從對應(yīng)的key中取出參數(shù)值粮坞。
具體代碼如下:
//封裝參數(shù)
NSDictionary *dic = @{@"param1":@"this is a string",@"param2":@[@2,@3,@3],@"param3":@123};
//調(diào)用方法
[self performSelector:@selector(testFunctionWithParams:) withObject:dic];
- (void)testFunctionWithParams:(NSDictionary *)paramDic {
NSLog(@"%s dic:%@",__FUNCTION__, paramDic);
}
b 使用objc_msgSend()傳遞
思路:利用objc_msgSend() 方法可以傳遞多個參數(shù)的特性調(diào)用方法執(zhí)行
具體代碼如下:
((void (*)(id,SEL,NSString *, NSArray *, NSInteger))objc_msgSend)(self, @selector(textFunctionWithParam:param2:param3:),@"111",@[@2,@3],123);
//有三個參數(shù)的方法
-(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}
c 用NSInvocation傳遞
思路:將方法調(diào)用采用NSInvocation調(diào)用,NSInvocation 不限制參數(shù)數(shù)量
這里可以了解一下NSInvocation的用法http://www.reibang.com/p/e24b3420f1b4
具體代碼如下:
//可以傳多個參數(shù)的方法
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects
{
// 方法簽名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
if (signature == nil) {
//可以拋出異常也可以不操作初狰。
}
// NSInvocation : 利用一個NSInvocation對象包裝一次方法調(diào)用(方法調(diào)用者莫杈、方法名、方法參數(shù)奢入、方法返回值)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
// 設(shè)置參數(shù)
NSInteger paramsCount = signature.numberOfArguments - 2; // 除self筝闹、_cmd以外的參數(shù)個數(shù)
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];
}
// 調(diào)用方法
[invocation invoke];
// 獲取返回值
id returnValue = nil;
if (signature.methodReturnLength) { // 有返回值類型,才去獲得返回值
[invocation getReturnValue:&returnValue];
}
return returnValue;
}
//調(diào)用方法
NSArray *paramArray = @[@"112",@[@2,@13],@12];
[self performSelector:@selector(textFunctionWithParam:param2:param3:) withObjects:paramArray];
//要調(diào)用的方法
-(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}
2 如何傳遞結(jié)構(gòu)體
思路:將結(jié)構(gòu)體封裝成NSValue對象
關(guān)于NSValue的更多內(nèi)容請參照:http://nshipster.cn/nsvalue/
typedef struct TTTestStrout{
int aaa;
int bbb;
} testStrout;
//傳結(jié)構(gòu)體
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);
}