NSMethodSignature、NSInvocation进行消息转发

xiaoxiao2021-02-28  13

方法的一般调用方式:

1、performSelector:withObject;

2、NSInvocation

什么时候使用NSInvocation:

performSelector:withObject能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那performSelector:withObject就显得费力了,这种情况下,我使用NSInvocation就显得相对简单些。

NSMethodSignature和NSInvocation的概述:

使用NSMethodSignature 和 NSInvocation 不仅可以完成对method的调用,也可以完成block的调用

NSMethodSignature:NSMethodSignature用于描述method的类型信息:返回值类型,及每个参数的类型

提供几个例子供参考:

- (id)performSelector:(SEL)aSelector withTheObjects:(NSArray*)objects{ //1、创建签名对象 // NSMethodSignature*signature = [self methodSignatureForSelector:aSelector]; NSMethodSignature*signature = [[self class] instanceMethodSignatureForSelector:aSelector]; //2、判断传入的方法是否存在 if (!signature) { //传入的方法不存在 就抛异常 NSString*info = [NSString stringWithFormat:@"-[%@ %@]:unrecognized selector sent to instance",[self class],NSStringFromSelector(aSelector)]; @throw [[NSException alloc] initWithName:@"方法没有" reason:info userInfo:nil]; return nil; } //3、创建NSInvocation对象 NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature]; //4、保存方法所属的对象 invocation.target = self; // index 0 invocation.selector = aSelector; // index 1 //5、设置参数 NSInteger arguments = signature.numberOfArguments -2; NSUInteger objectsCount = objects.count; NSInteger count = MIN(arguments, objectsCount); [self setInv:invocation andArgs:objects argsCount:count]; //6、调用NSinvocation对象 [invocation invoke]; //7、获取返回值 id res = nil; if (signature.methodReturnLength ==0) return nil; //getReturnValue获取返回值 [invocation getReturnValue:&res]; return res; } - (nullable id)performSelectorWithTheArgs:(SEL)sel, ...{ NSMethodSignature * sig = [self methodSignatureForSelector:sel]; if (!sig) { [self doesNotRecognizeSelector:sel]; return nil; } NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig]; if (!inv) { [self doesNotRecognizeSelector:sel]; return nil; } // 设置消息接收者 [inv setTarget:self]; // index = 0 // 设置调用的方法 [inv setSelector:sel]; // index = 1 // 获取参数 va_list args; va_start(args, sel); [self setInv:inv sigT:sig andArgs:args]; va_end(args); [inv invoke]; // 获取返回值 id res = nil; if (sig.methodReturnLength ==0) return nil; //getReturnValue获取返回值 [inv getReturnValue:&res]; return res; } #pragma mark - 传递一个值的block - (void)performSelectorWithTheBlock:(void(^)(int value))block { // 获取block NSMethodSignature *signature = aspect_blockMethodSignature(block,NULL); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:block]; // 此处待考虑 int a=2; [invocation setArgument:&a atIndex:1]; [invocation invoke]; }

调用方式:

UIView *view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 30, 30)]; view.backgroundColor = [UIColor redColor]; [self.view addSubview:view]; //[view performSelector:@selector(setBackgroundColor:) withTheObjects:@[[UIColor greenColor]]]; [view performSelectorWithTheArgs:@selector(setBackgroundColor:), [UIColor greenColor], [UIColor yellowColor]];

资源代码: https://github.com/MisterZhouZhou/iOSToolsDemo/blob/master/OCToolsDemo/OCToolsDemo/OCTools/Category/NSObject+performSelector.m

参考资源:

http://www.jianshu.com/p/da96980648b6https://github.com/ibireme/YYKit/blob/master/YYKit/Base/Foundation/NSObject+YYAdd.m
转载请注明原文地址: https://www.6miu.com/read-750102.html

最新回复(0)