专栏首页APP自动化测试Objective-C中NSInvocation的使用

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获得返回的类型编码,因此可以推断返回值的具体类型

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用Apple Configurator 2提取商店ipa or app文件

    之前我们可以通过iTunes来提取商店的ipa文件, 但12.+版本以后这个功能就被拿掉了

    周希
  • iOS模拟器命令

    注意模拟器不支持直接安装ipa, 需要将ipa解压出来使用xxx.app文件进行安装

    周希
  • Android自动化测试探索(一)adb详细介绍

    adb,即Android Debug Bridge,它是Android开发/测试人员不可替代的强大工具

    周希
  • 阶段01Java基础day06面向对象01

    声明:本文为原创,作者为 对弈,转载时请保留本声明及附带文章链接:http://www.duiyi.xyz/c%e5%ae%9e%e7%8e%b0%e9%9b%...

    对弈
  • Java基础笔记06

    dreamkong
  • 技术分享 | 什么是半一致性读?

    爱可生 MySQL DBA 团队成员,Oracle 10g OCM,MySQL 5.7 OCP,擅长数据库性能问题诊断、事务与锁问题的分析等,负责处理客户 My...

    爱可生开源社区
  • Rust Stable 1.45 中的 神奇 Bug 解读

    今天,Rust 官方仓库里报告了一个神奇的Bug,该 Bug 似乎动摇了 Rust 的世界法则,让我们一探究竟到底是否如此。

    张汉东
  • 一些笔记20200714

    this.$once('hook:beforeDestroy', function () { picker.destroy() }):

    wade
  • MongoDB集群管理工具UMongo 原

    UMongo (前身是 JMongoBrowser) 是一个图形化界面的工具,用来浏览和管理 MongoDB 集群,支持 Linux, Windows 和 Ma...

    拓荒者
  • Java--类和对象之组合和继承

    SuperHeroes

扫码关注云+社区

领取腾讯云代金券