NSInvocation简单用法

在 iOS中可以直接调用某个对象的消息方式有两种:

一种是performSelector:withObject     另一种就是NSInvocation

第一种方式比较简单,能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定。那么在这种情况下,我们就可以使用NSInvocation来进行这些相对复杂的操作。


1、

DZPerson.h:

#import <Foundation/Foundation.h>

@interface DZPerson : NSObject


@end

.h文件中并不需要有方法的声明



DZPerson.m

#import "DZPerson.h"

@implementation DZPerson

- (void) showName:(NSString *) name {
    NSLog(@"name : %@", name);
}
- (void) showName:(NSString *) name andAge:(NSUInteger) age {
    NSLog(@"name : %@, age : %lu", name, (unsigned long)age);
}
- (NSString *) getAgeAndNameWithName:(NSString *) name {
    NSString * str = [NSString stringWithFormat:@"age : 15, name : %@", name];
    NSLog(@"%@", str);
    return str;
}

- (NSInteger) getAge {
    return 1970;
}

@end

2、测试:

代码中有详细的注释:

//
//  ViewController.m
//  001-nsinvocation
//
//

#import "ViewController.h"
#import "DZPerson.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.view.backgroundColor = [UIColor whiteColor];
    
    DZPerson * p1 = [[DZPerson alloc] init];
    
    //1、一个参数
    NSMethodSignature * methodSignature1 = [[p1 class] instanceMethodSignatureForSelector:@selector(showName:)];
    NSInvocation * invocation1 = [NSInvocation invocationWithMethodSignature:methodSignature1];
    
    [invocation1 setTarget:p1];
    [invocation1 setSelector:@selector(showName:)];
    
    NSString * name = @"ldz";
    
    //如果此消息有参数需要传入,那么就需要按照如下方法进行参数设置,需要注意的是,atIndex的下标必须从2开始。原因为:0 1 两个参数已经被target 和selector占用
    [invocation1 setArgument:&name atIndex:2];
    //防止参数被释放掉
    [invocation1 retainArguments];
    //调用
    [invocation1 invoke];
    
    
    //2、两个参数
    NSMethodSignature * methodSignature2 = [[p1 class] instanceMethodSignatureForSelector:@selector(showName:andAge:)];
    NSInvocation * invocation2 = [NSInvocation invocationWithMethodSignature:methodSignature2];
    
    [invocation2 setTarget:p1];
    [invocation2 setSelector:@selector(showName:andAge:)];
    
    NSUInteger age = 18;
    
    [invocation2 setArgument:&name atIndex:2];
    [invocation2 setArgument:&age atIndex:3];
    [invocation2 retainArguments];
    [invocation2 invoke];

    
    //3、有返回值的情况
    NSMethodSignature * methodSignature3 = [[p1 class] instanceMethodSignatureForSelector:@selector(getAgeAndNameWithName:)];
    NSInvocation * invocation3 = [NSInvocation invocationWithMethodSignature:methodSignature3];
    
    [invocation3 setTarget:p1];
    [invocation3 setSelector:@selector(getAgeAndNameWithName:)];
    
    
    [invocation3 setArgument:&name atIndex:2];
    [invocation3 retainArguments];
    [invocation3 invoke];
    
    
    //获取返回值类型
    const char * returnValueType = methodSignature3.methodReturnType;
    NSLog(@"returnValueType : %s", returnValueType);
    
    //声明一个返回值变量
    id returnValue;
    
    //如果没有返回值,也就是消息声明为void,那么returnValue = nil
    if (!strcmp(returnValueType, @encode(void))) {
        NSLog(@"没有返回值,即返回值类型为void");
        returnValue = nil;
    }else if (!strcmp(returnValueType, @encode(id))){
        //如果返回值为对象,那么为变量赋值
        NSLog(@"返回值类型为对象");
        [invocation3 getReturnValue:&returnValue];
    }else {
        //如果返回值为普通类型,如NSInteger, NSUInteger ,BOOL等
        NSLog(@"返回类型为普通类型");
        
        //首先获取返回值长度
        NSUInteger returnValueLenth = methodSignature3.methodReturnLength;
        
        //根据长度申请内存
        void * retValue = (void *)malloc(returnValueLenth);
        
        //为retValue赋值
        [invocation3 getReturnValue:retValue];
        
        if (!strcmp(returnValueType, @encode(BOOL))) {
            returnValue = [NSNumber numberWithBool:*((BOOL *)retValue)];
        }else if (!strcmp(returnValueType, @encode(NSInteger))){
            returnValue = [NSNumber numberWithInteger:*((NSInteger *) retValue)];
        }
        //。。。  余下省略
        
    }
    
    NSLog(@"返回值是:%@", returnValue);
    
    
    
    
    //4、返回类型为普通类型的情况
    
    NSMethodSignature * methodSignature4 = [[p1 class] instanceMethodSignatureForSelector:@selector(getAge)];
    NSInvocation * invocation4 = [NSInvocation invocationWithMethodSignature:methodSignature3];
    
    [invocation4 setTarget:p1];
    [invocation4 setSelector:@selector(getAge)];
    
    [invocation4 invoke];
    
    
    //获取返回值类型
    const char * returnValueType4 = methodSignature4.methodReturnType;
    NSLog(@"returnValueType : %c", *returnValueType4);
    
    //声明一个返回值变量
    id returnValue4;
    
    //如果没有返回值,也就是消息声明为void,那么returnValue = nil
    if (!strcmp(returnValueType4, @encode(void))) {
        NSLog(@"没有返回值,即返回值类型为void");
        returnValue4 = nil;
    }else if (!strcmp(returnValueType4, @encode(id))){
        //如果返回值为对象,那么为变量赋值
        NSLog(@"返回值类型为对象");
        [invocation4 getReturnValue:&returnValue4];
    }else {
        //如果返回值为普通类型,如NSInteger, NSUInteger ,BOOL等
        NSLog(@"返回类型为普通类型");
        
        //首先获取返回值长度
        NSUInteger returnValueLenth4 = methodSignature4.methodReturnLength;
        
        //根据长度申请内存
        void * retValue4 = (void *)malloc(returnValueLenth4);
        
        //为retValue赋值
        [invocation4 getReturnValue:retValue4];
        
        if (!strcmp(returnValueType4, @encode(BOOL))) {
            returnValue4 = [NSNumber numberWithBool:*((BOOL *)retValue4)];
        }else if (!strcmp(returnValueType4, @encode(NSInteger))){
            returnValue4 = [NSNumber numberWithInteger:*((NSInteger *) retValue4)];
        }
        //。。。  余下省略
        
    }
    
    NSLog(@"返回值是:%@", returnValue4);
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end


输出:

2016-02-16 14:23:00.093 001-nsinvocation[2766:96619] name : ldz
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] name : ldz, age : 18
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] age : 15, name : ldz
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] returnValueType : @
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] 返回值类型为对象
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] 返回值是:age : 15, name : ldz
2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] returnValueType : q
2016-02-16 14:23:00.095 001-nsinvocation[2766:96619] 返回类型为普通类型
2016-02-16 14:23:00.095 001-nsinvocation[2766:96619] 返回值是:1970



3、其中Objective-C类型编码为:

编码含义
cchar
iint
sshort
llong
在64位程序中,l为32位
qlong long
C(大写)unsigned char
I(大写)unsigned int
S(大写)unsigned short
Lunsigned long
Qunsigned long long
ffloat
ddouble
BC++标准的bool或者C99标准的_Bool
vvoid
*字符串(char *)
@对象(无论是静态指定的还是通过id引用的)
#类(class)
:方法选标(SEL)
[array type]数组
{name=type...}结构体
(name=type...)联合体
bnumnum个bit的位域
^typetype类型的指针
?未知类型(其他的情况,一般用来指函数指针)













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值