【iOS】利用NSMethodSignature和NSInvoc
2018-03-10 本文已影响42人
zhangPeng丶
简书:http://www.jianshu.com/u/5690b3ad0a6f
Blog:http://blog.zhangpeng.site
GitHub:https://github.com/fullstack-zhangpeng
方法调用的两种方式
-
performSelector: withObject:
优点: 可以调用运行时添加方法
缺点: 在编译阶段不会做校验。只有在程序运行的时候,才会知道是否存在即将调用的方法,如果方法不存在,程序会崩溃。因此为了保证程序的健壮,在调用方法前应该使用
- (BOOL)respondsToSelector:(SEL)aSelector
,检查方法是否实现。 -
直接调用方法
优点: 在编译阶段就会教研方法是否存在,Xcode会有相应提示
缺点: 局限性大,如果想调用某个方法,必须先实现这个方法,不如
performSelector: withObject:
灵活。
升级版:利用NSMethodSignature和NSInvocation实现方法调用
NSMethodSignature
通过NSMethodSignature
获取方法的参数类型和返回值类型
常用方法
//获取类方法的签名
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector
//获取实例方法的签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
NSInvocation
NSInvocation
可以说是performSelector: withObject:
的升级版,可以调用较为复杂的方法,进行参数、返回值的处理等;
举例
NSString *str = @"Test";
str = [str stringByAppendingString:@" AppendingString"];
NSLog(@"str: %@", str);
//需要调用的方法
SEL selector = @selector(stringByAppendingString:);
//获取方法签名
NSMethodSignature *signature = [str methodSignatureForSelector:selector];
//创建 NSInvocation 对象
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
//设置消息接受对象
invocation.target = str;
//设置发送的消息
invocation.selector = selector;
//建议通过signature.numberOfArgument获取参数个数
//可以保证不多参,不少参
//这边减2的原因是:
//0位置的参数是 目标(self)
//1位置的参数是 selector(_cmd)
//所以2位置才是所需要的第一个参数
NSInteger paramCount = signature.numberOfArguments - 2;
NSLog(@"paramCount: %@", @(paramCount));
for (int i = 0; i < paramCount; i++) {
//设置参数
[invocation setArgument:&str atIndex:i + 2];
}
//执行 invocation
[invocation invoke];
//获取返回值
id returnValue = nil;
if (signature.methodReturnLength) {
[invocation getReturnValue:&returnValue];
}
NSLog(@"returnValue: %@", returnValue);