美文网首页
NSInvocation应用与理解

NSInvocation应用与理解

作者: lltree | 来源:发表于2018-06-08 15:46 被阅读32次

NSMethodSignature 顾名思义应该就是“方法签名”,类似于C++中的编译器时的函数签名。苹果官方定义该类为对方法的参数、返回类似进行封装,协同NSInvocation实现消息转发。通过消息转发实现类似C++中的多重继承;

NSMethodSignature 主要提供了一下功能:

  • 1、方法参数个数
  • 2、方法参数类型
  • 3、方法返回值类型

签名方法的生成

我们可以通过类的实例方法或者类方法获取该类下的(SEL)aSelector 的方法签名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");

+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");

通过实例获取某一个方法签名:

 NSMethodSignature* methodSig = [[[someClass alloc] init] methodSignatureForSelector:action];

通过类获取某一个方法签名:

NSMethodSignature *sig = [[someClass class] instanceMethodSignatureForSelector:myMethod];

获取方法参数个数及类型

NSUInteger argCount = [sig numberOfArguments];
   NSLog(@"argCount:%ld", argCount);

   for (NSInteger i=0; i<argCount; i++) {
       NSLog(@"%s", [sig getArgumentTypeAtIndex:i]);
   }

作者:城市之光
链接:https://www.jianshu.com/p/7e2efff789e2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

获取方法签名的返回值类型

并且我们可以通过

@property (readonly) const char *methodReturnType NS_RETURNS_INNER_POINTER;

从而完成

#pragma mark - private methods
- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params
{
    NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
    if(methodSig == nil) {
        return nil;
    }
    const char* retType = [methodSig methodReturnType];
    
 //返回void 类型
    if (strcmp(retType, @encode(void)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        return nil;
    }
    
//返回NSInteger 类型
    if (strcmp(retType, @encode(NSInteger)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];

//获取到方法返回值
        NSInteger result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
    if (strcmp(retType, @encode(BOOL)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
//获取到方法返回值
        BOOL result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
    if (strcmp(retType, @encode(CGFloat)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
//获取到方法返回值
        CGFloat result = 0;
        [invocation getReturnValue:&result];
        return @(result);


    }
    
    if (strcmp(retType, @encode(NSUInteger)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];

//获取到方法返回值
        NSUInteger result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
}

相关文章

网友评论

      本文标题:NSInvocation应用与理解

      本文链接:https://www.haomeiwen.com/subject/abjasftx.html