美文网首页
NSInvocation的使用

NSInvocation的使用

作者: 云天涯丶 | 来源:发表于2018-04-09 17:17 被阅读13次

一、介绍

在 iOS中可以直接调用方法的方式有两种:

1、performSelector:withObject;
2、NSInvocation

前者最多只能有两个参数,多参的情况下需要用NSInvocation来处理。

NSInvocation.h文件:

@interface NSInvocation : NSObject {
@private
    void *_frame;
    void *_retdata;
    id _signature;
    id _container;
    uint8_t _retainedArgs;
    uint8_t _reserved[15];
}
// 通过NSMethodSignature对象创建NSInvocation对象(NSMethodSignature为方法签名类)
+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)sig;

@property (readonly, retain) NSMethodSignature *methodSignature;

// 保留参数,将传入的所有参数以及target都retain一遍
- (void)retainArguments;

// 调用retainArguments之前,值为NO,调用之后值为YES
@property (readonly) BOOL argumentsRetained;

// 消息调用者
@property (nullable, assign) id target;

// 调用的消息
@property SEL selector;

// 获取消息返回值
- (void)getReturnValue:(void *)retLoc;
// 设置消息返回值
- (void)setReturnValue:(void *)retLoc;

// 获取消息参数
- (void)getArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
// 设置消息参数
- (void)setArgument:(void *)argumentLocation atIndex:(NSInteger)idx;

// 发送消息(执行)
- (void)invoke;
// target发送消息
- (void)invokeWithTarget:(id)target;

@end

上面介绍到创建一个NSInvocation对象需要NSMethodSignature对象(方法签名类),所以我们再了解下NSMethodSignature类

@interface NSMethodSignature : NSObject {
@private
    void *_private;
    void *_reserved[5];
    unsigned long _flags;
}

// 通过Objective-C类型编码(Objective-C Type Encodings)创建一个NSMethodSignature对象
+ (nullable NSMethodSignature *)signatureWithObjCTypes:(const char *)types;

// 参数个数
@property (readonly) NSUInteger numberOfArguments;
// 获取参数类型
- (const char *)getArgumentTypeAtIndex:(NSUInteger)idx NS_RETURNS_INNER_POINTER;

// 所有参数占用的字节数
@property (readonly) NSUInteger frameLength;

// 通过分布式对象调用时,接收者是否是异步的。
- (BOOL)isOneway;

// 方法返回类型
@property (readonly) const char *methodReturnType NS_RETURNS_INNER_POINTER;
// 返回值所需的字节数。
@property (readonly) NSUInteger methodReturnLength;

@end

二、使用

1、无参无返

- (void)invocation{
    SEL sel = @selector(run);
    NSMethodSignature *sign = [[self class] instanceMethodSignatureForSelector:sel];
    NSInvocation *invo = [NSInvocation invocationWithMethodSignature:sign];
    invo.target = self;
    invo.selector = sel;
    [invo invoke];
}

- (void)run{
    NSLog(@"run");
}

2、有参无返

- (void)invocation{
    SEL sel = @selector(runArg1:arg2:arg3:);
    NSMethodSignature *sign = [[self class] instanceMethodSignatureForSelector:sel];
    NSInvocation *invo = [NSInvocation invocationWithMethodSignature:sign];
    invo.target = self;
    invo.selector = sel;
    // 参数设置
    NSString *name = @"小明";
    NSInteger age = 18;
    NSArray *family = @[@"爷爷",@"奶奶",@"爸爸",@"妈妈"];
    // 0是target 1是selector
    [invo setArgument:&name atIndex:2];
    [invo setArgument:&age atIndex:3];
    [invo setArgument:&family atIndex:4];
    
    [invo invoke];
}

- (void)runArg1:(NSString *)arg1 arg2:(NSInteger)arg2 arg3:(NSArray *)arg3{
    NSLog(@"%@ %ld %@",arg1,(long)arg2,arg3);
}

3、有参有返

- (void)invocation{
    SEL sel = @selector(runArg1:arg2:arg3:);
    NSMethodSignature *sign = [[self class] instanceMethodSignatureForSelector:sel];
    NSInvocation *invo = [NSInvocation invocationWithMethodSignature:sign];
    invo.target = self;
    invo.selector = sel;
    // 参数设置
    NSString *name = @"小明";
    NSInteger age = 18;
    NSArray *family = @[@"爸爸",@"妈妈"];
    // 0是target 1是selector
    [invo setArgument:&name atIndex:2];
    [invo setArgument:&age atIndex:3];
    [invo setArgument:&family atIndex:4];
    
    [invo invoke];
    
    // 获取返回值
    void *re;
    [invo getReturnValue:&re];
    NSLog(@"%@",re);
}

- (NSString *)runArg1:(NSString *)arg1 arg2:(NSInteger)arg2 arg3:(NSArray *)arg3{
    NSLog(@"%@ %ld %@",arg1,(long)arg2,arg3);
    return [NSString stringWithFormat:@"%@今年%ld岁,家庭成员有%@,%@",arg1,(long)arg2,arg3[0],arg3[1]];
}

注:这里要说明一点,若用NSString 类型去获取返回值会crash。具体看这篇

参考:https://blog.csdn.net/ssirreplaceable/article/details/53375972

相关文章

  • NSInvocation个人理解

    NSInvocation的使用: //NSInvocation;用来包装方法和对应的对象,它可以存储方法的名称,对...

  • NSInvocation

    NSInvocation的基本使用 11 异常处理

  • NSInvocation 使用

    NSString*result1 = [selfappend:@"a"withStr2:@"b"andStr3:@...

  • NSInvocation使用

    NSInvocation NSInvocation是一个消息调用类,主要作用是存储和传递消息。它存储的信息包含了一...

  • NSInvocation的使用

    一、介绍 在 iOS中可以直接调用方法的方式有两种: 1、performSelector:withObject;2...

  • NSInvocation的使用

    在iOS中方法调用的方式:第一种方式 (id)performSelector:(SEL)aSelector; (i...

  • NSInvocation的使用

    背景 在最近的项目开发中遇到了一个很别扭的问题。项目本身是一个SDK,供业务方App集成使用。SDK内部有网络请求...

  • NSInvocation的使用

    NSInvocation的使用 1 生成需要调用方法的签名NSMethodSignature,使用根据调用的Sel...

  • NSInvocation的使用

    1.NSInvocation的作用 封装了方法调用对象、方法选择器、参数、返回值等,可以给对象发送一个参数大于两个...

  • NSInvocation的使用

    版本:iOS13.6 一、简介 通常调用方法的方式是使用[实例 方法名]或[实例 方法名:参数] 若该方法没有公开...

网友评论

      本文标题:NSInvocation的使用

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