zoukankan      html  css  js  c++  java
  • Objective-C中NSInvocation的使用

    OC中调用方法某个对象的消息呦两种方式:

    #1. performanceSelector: withObject:

    #2. NSInvocation.

    第一个PerformaceSelector比较常用, 也比较简单。 但是这个方式最多只能传递2个参数

    当需要2个以上参数时就只能用NSInvocation了

    直接上代码吧, 会注释清楚

    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
        //用performanceSelector调用三个参数的方法, 但只传递2个参数, 这样方法的第三个参数会自动取我们传的第二个的值
        [self performSelector:@selector(printStr1:Str2:Str3:) withObject:@"str1" withObject:@"str2"];
        
        //1.创建方法签名
        NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(printStr1:Str2:Str3:)];
        
        //2.根据方法签名来创建NSInvocation对象, 在这之前最好先判断下前面创建的signature是否为nil, 方法不存时就是nil
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        
        //设置方法的调用者
        invocation.target = self;
        //设置方法名, 这里一定要跟方法签名类中的方法名一致
        invocation.selector = @selector(printStr1:Str2:Str3:);
        
        //自定义三个参数
        NSString *str1 = @"First argument";
        NSString *str2 = @"Second argument";
        NSString *str3 = @"Third argument";
        
        //从第二个位置开始添加参数, 因为前面两个位置已经被占用了, 分别时self(target), selector(_cmd)
        [invocation setArgument:&str1 atIndex:2];
        [invocation setArgument:&str2 atIndex:3];
        [invocation setArgument:&str3 atIndex:4];
        
        //3.调用invoke方法
        [invocation invoke];
        
    }
    
    - (void)printStr1:(NSString *)str1 Str2:(NSString *)str2 Str3:(NSString *)str3 {
        
        NSLog(@"%@", str1);
        NSLog(@"%@", str2);
        NSLog(@"%@", str3);
    }
    
    @end

    输出结果为:

    2017-01-06 11:55:07.398 BezierPathDemo[1203:97184] str1
    2017-01-06 11:55:07.398 BezierPathDemo[1203:97184] str2
    2017-01-06 11:55:07.399 BezierPathDemo[1203:97184] str2
    2017-01-06 11:55:07.399 BezierPathDemo[1203:97184] First argument
    2017-01-06 11:55:07.399 BezierPathDemo[1203:97184] Second argument
    2017-01-06 11:55:07.399 BezierPathDemo[1203:97184] Third argument

    NSInvocation使用时有下面三个地方要注意下

    1、如果调用的方法不存在

    //此时我们应该判断方法是否存在,如果不存在这抛出异常
    if (signature == nil) {
    //aSelector为传进来的方法
    NSString *info = [NSString stringWithFormat:@"%@方法找不到", NSStringFromSelector(aSelector)];
    [NSException raise:@"方法调用出现异常" format:info, nil];
        }

    2、方法的参数个数与外界传进来的参数数组元素个数不符

    //此处不能通过遍历参数数组来设置参数,因为外界传进来的参数个数是不可控的
    //因此通过numberOfArguments方法获取的参数个数,是包含self和_cmd的,然后比较方法需要的参数和外界传进来的参数个数,并且取它们之间的最小值
    NSUInteger argsCount = signature.numberOfArguments - 2;
    NSUInteger arrCount = objects.count;
    NSUInteger count = MIN(argsCount, arrCount);
    for (int i = 0; i < count; i++) {
        id obj = objects[i];
        // 判断需要设置的参数是否是NSNull, 如果是就设置为nil
        if ([obj isKindOfClass:[NSNull class]]) {
            obj = nil;
        }
    [invocation setArgument:&obj atIndex:i + 2];
    }

    3、判断当前调用的方法是否有返回值

    //方法一:
    id res = nil;
    if (signature.methodReturnLength != 0) {//有返回值
        //将返回值赋值给res
        [invocation getReturnValue:&res];
    }
    return res;
    
    //方法二:
    //可以通过signature.methodReturnType获得返回的类型编码,因此可以推断返回值的具体类型

     

  • 相关阅读:
    Android编码规范03
    Android编码规范02
    Android编码规范01
    函数返回值类型为枚举类型
    ObjectAnimator属性动画应用demo
    n个元素的入栈顺序有多少种出栈顺序?
    JNI笔记1
    字符串——面试题1:统计一行字符中有多少个单词?
    快速排序算法
    es6之 async await 使用小计
  • 原文地址:https://www.cnblogs.com/zhouxihi/p/6255848.html
Copyright © 2011-2022 走看看