iOS开发之NSInvocation

作者: 纳萨立克 | 来源:发表于2016-03-21 17:58 被阅读870次

    一.概述

    在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;
    }
    
    
    

    相关文章

      网友评论

        本文标题:iOS开发之NSInvocation

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