iOS开发之NSInvocation

一.概述

在iOS中我们直接调某个对象的消息的方式有2种

  • 系统NSObject类型中提供了2个方法

// 一个参数
[self performSelector:<#(SEL)#> withObject:<#(id)#>];
// 两个参数
[self performSelector:<#(SEL)#> withObject:<#(id)#> withObject:<#(id)#>];


- 使用NSInvocation.

### 二. NSInvocation的使用

```objc
- (void)viewDidLoad {
  [super viewDidLoad];

  //方法
  SEL selector = @selector(run);
  //初始化方法签名(方法的描述)   
   NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
  // NSInvocation : 利用一个NSInvocation对象包装一次方法调用(方法调用者、方法名、方法参数、方法返回值)
  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
  //设置调用者
  invocation.target = self;
  //设置调用方法
  invocation.selector = selector;
  //设置参数
  NSUInteger object = 5;
  //参数从2开始,index为0表示target,1为_cmd 
  [invocation setArgument:&object atIndex:2];
  //调用方法
  [invocation invoke];

}
-(void)run:(NSInteger)num{


  NSLog(@"run");
}

三. NSInvocation实现多参数的封装

系统的NSObject提供的performSelector的方法只提供了最多两个参数的调用,我们可以使用NSInvocation封装一个多个参数的performSelector方法.

#import <Foundation/Foundation.h>

@interface NSObject (MutiPerform)

-(id)performSelector:(SEL)Selector withObjects:(NSArray *)objects;
@end


#import "NSObject+MutiPerform.h"

@implementation NSObject (MutiPerform)

-(id)performSelector:(SEL)selector withObjects:(NSArray *)objects{

    //初始化方法签名
    NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
    
    // 如果方法selector不存在
    
    if(signature == nil){

        // 抛出异常
        NSString *reason = [NSString stringWithFormat:@"%@方法不存在",NSStringFromSelector(selector)];
        @throw [NSException exceptionWithName:@"error" reason:reason userInfo:nil];
    }
    
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

    invocation.target = self;
    invocation.selector = selector;
    
    //参数个数signature.numberOfArguments 默认有一个_cmd 一个target 所以要-2
    NSInteger paramsCount = signature.numberOfArguments - 2;
    
    // 当objects的个数多于函数的参数的时候,取前面的参数
    //当当objects的个数少于函数的参数的时候,不需要设置,默认为nil
    paramsCount = MIN(paramsCount, objects.count);
    
    for (NSInteger index = 0; index < paramsCount; index++) {
        
        id object = objects[index];

        // 对参数是nil的处理
        if([object isKindOfClass:[NSNull class]]) continue;
        
        [invocation setArgument:&object atIndex:index+2];

    }
    //调用方法
    [invocation invoke];

    // 获取返回值
    id returnValue = nil;
    
    //signature.methodReturnLength == 0 说明给方法没有返回值
    if (signature.methodReturnLength) {

        //获取返回值
        [invocation getReturnValue:&returnValue];
    }
    
    return returnValue;
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,899评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 6,634评论 0 7
  • Objective-C中有两个NSObject,一个是NSObject类,另一个是NSObject协议。而其中NS...
    ScaryMonsterLyn阅读 4,090评论 0 2
  • 目录 Objective-C Runtime到底是什么 Objective-C的元素认知 Runtime详解 应用...
    Ryan___阅读 5,946评论 1 3
  • 像我,有时候睡下去了,就不想起来,现在也是在卧榻上码字,我追求着一种安全感,可能是我从小就比较缺失吧,当然也有...
    简碸阅读 1,598评论 0 0

友情链接更多精彩内容