方法的一般调用方式:
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]];
参考资源: