NSInvocation简单用法

来源:互联网 发布:wow60 n服数据库 编辑:程序博客网 时间:2024/06/14 02:39

在 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 : ldz2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] name : ldz, age : 182016-02-16 14:23:00.094 001-nsinvocation[2766:96619] age : 15, name : ldz2016-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 : ldz2016-02-16 14:23:00.094 001-nsinvocation[2766:96619] returnValueType : q2016-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类型编码为:

编码含义cchariintsshortllong
在64位程序中,l为32位qlong longC(大写)unsigned charI(大写)unsigned intS(大写)unsigned shortLunsigned longQunsigned long longffloatddoubleBC++标准的bool或者C99标准的_Boolvvoid*字符串(char *)@对象(无论是静态指定的还是通过id引用的)#类(class):方法选标(SEL)[array type]数组{name=type...}结构体(name=type...)联合体bnumnum个bit的位域^typetype类型的指针?未知类型(其他的情况,一般用来指函数指针)













0 0
原创粉丝点击