NSInvocation使一个OC消息转换为一个对象,存储着要转发的消息,包含了消息中的target、selector、参数、返回值。参数可以直接被设置,在NSInvocation对象被派发时自动获取返回值。
只要保证方法的签名不变,其target、选择子、参数都可以变化,可重复的派发。
实现OC调用,调用自定义方法⤵️,将消息转发给 target 的 selector 方法
- (void)invoke:(id)target selector:(SEL)selector arguments:(NSArray *)arguments
{
//生成selector的函数签名
//若有另一个selector1与这个selector返回值、参数列表相同,也可以用selector1的函数签名
NSMethodSignature *signature = [[target class] instanceMethodSignatureForSelector:selector];
//根据函数签名生成一个NSInvocation对象,NSInvocation对象的生成仅能通过其类方法实现
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
//设置target、selector,并且target、selector分别占据其参数列表第0个和第1个的位置
[invocation setTarget:target];
[invocation setSelector:method];
NSNumber *num = arguments[0];
NSString *str = arguments[1];
[invocation setArgument:&num atIndex:2];
[invocation setArgument:&str atIndex:3];
//转发此消息
[invocation invoke];
//获取其返回值
NSString *returnValue;
[invocation getReturnValue:&returnValue]; //此时,returnValue就保存着selector的返回值
}
在 NSInvocation 参数列表中,其 target、selector 分别占据了第0个和第1个位置,所以实际的参数从2开始往后写,所以其参数列表还可以这么写:
[invocation setArgument:&target atIndex:0];
[invocation setArgument:&selector atIndex:1];
target 中 selector 方法⤵️,必须满足NSInvocation中所设置的,两个参数:第一个 NSNumber 类型,第二个为 NSString 类型,并且有函数返回值。
- (NSString *)hello:(NSNumber *)num arg1:(NSString *)arg1
{
NSLog(@"hello");
NSLog(@"num:%d",num.intValue);
NSLog(@"arg1:%@",arg1);
return @"123";
}
由于NSInvocation不会默认保留其参数,在创建NSInvocation类和使用它时,其参数可能被销毁了,这就需要显示的保留这些参数。
- (void)retainArguments;