RuntimeInvoker是一個(gè)Objective-C反射調(diào)用庫的封裝。
https://github.com/cyanzhong/RuntimeInvoker
以下是一些簡單的使用舉例:
-(void)test{
NSString *s = [self invoke:@"fun1"];
NSLog(@"---------%@",s);
}
-(NSString *)fun1{
return @"fun1";
}
-(void)test{
[self invoke:@"fun2:" args:@(YES),nil];
}
-(void)fun2:(BOOL)bo{
if (bo) {
NSLog(@"fun2 yes");
}else{
NSLog(@"fun2 no");
}
}
-(void)test{
NSString *s = [[self class] invoke:@"fun3:" args:@"abc",nil];
NSLog(@"---------%@",s);
}
+(NSString *)fun3:(NSString *)str{
return [NSString stringWithFormat:@"fun3 %@",str];
}
-(void)test{
NSString *s = [@"AppDelegate" invokeClassMethod:@"fun4:" args:@"abc",nil];
NSLog(@"---------%@",s);
}
+(NSString *)fun4:(NSString *)str{
return [NSString stringWithFormat:@"fun4 %@",str];
}
如果類是由字符串過去的,需要用invokeClassMethod替換invoke。
遇到這樣一個(gè)問題,方法如下:
-(void)callFun6:(NSString *)str1 index:(int)index f:(CGFloat)f point:(CGPoint)p;
我在拿到類對(duì)象的情況下,需要調(diào)用這個(gè)函數(shù),該怎么做?
見下面代碼:
TartetObject *target = [TartetObject new];
id obj = target;
NSString *str1 = @"2";
NSInteger index = 3;
CGFloat f = 3.1415926;
NSString *selStr = @"callFun6:index:f:point:";
// SEL sel = NSSelectorFromString(selStr);
CGPoint point = CGPointMake(32.121, 195.321);
[obj invoke:selStr args:str1,[NSNumber numberWithInt:index],[NSNumber numberWithFloat:f],[NSValue valueWithCGPoint:point],nil];
執(zhí)行,會(huì)發(fā)現(xiàn)CGpoint沒有傳值成功。閱讀RuntimeInvoker代碼可以發(fā)現(xiàn)作者在invocationWithArguments函數(shù)中少寫了一部分代碼。

后面補(bǔ)上point的類型
case RIMethodArgumentTypeCGPoint: {
CGPoint p = [argument CGPointValue];
[invocation setArgument:&p atIndex:index];
} break;
再跑一遍,傳參數(shù)成功了!
如果參數(shù)帶有block該怎么處理呢?
函數(shù)原型如下:
-(void)callFun6:(NSString *)str1 index:(int)index f:(CGFloat)f point:(CGPoint)p callBack:(void(^)(NSString *))block{
NSLog(@"callFun6 = %@%d%.2f;x=%.2fy=%.2f",str1,index,f,p.x,p.y);
block(@"abcdefg");
}
調(diào)用他:
TartetObject *target = [TartetObject new];
id obj = target;
NSString *str1 = @"2";
NSInteger index = 3;
CGFloat f = 3.1415926;
NSString *selStr = @"callFun6:index:f:point:callBack:";
CGPoint point = CGPointMake(32.121, 195.321);
void (^callblock)(NSString*) = ^(NSString * str){
NSLog(@"------------%@",str);
[target callFun1];
};
[obj invoke:selStr args:str1,[NSNumber numberWithInt:index],[NSNumber numberWithFloat:f],[NSValue valueWithCGPoint:point],callblock,nil];
發(fā)現(xiàn)出錯(cuò)了,block傳過來是空的。
看下RuntimeInvoker代碼,是的確沒有處理參數(shù)是block的情況。我們手動(dòng)改一下,代碼如下:

在判斷為未知類型的情況下,看下這個(gè)類是否是block。如果是block,就直接把參數(shù)傳遞過去。當(dāng)然,在未知情況下直接把參數(shù)傳遞過去也是可以的。
好了,RuntimeInvoker基本上可以滿足我們?nèi)粘J褂眯枨罅恕?/p>