NSInvocation直接调用某个对象的消息

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

一种是performSelector:withObject;

再一种就是NSInvocation。

第一种方式比较简单,能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定。那么在这种情况下,我们就可以使用NSInvocation来进行这些相对复杂的操作。在高级点的, block的结构体里面也是有函数的, 函数就可以通过NSInvocation调用 , 比较出名的Aspects框架就使用了NSInvocation调用block.

1、NSInvocation的作用
封装了 方法调用对象、方法选择器、参数、返回值等,可以给对象发送一个参数大于两个的消息;
2、优势
NSInvocation,它可以设置多个参数;
3、使用方式

  • 通过NSObject(或者子类都可以) 生成方法签名
  • 通过方法签名生成 NSInvocation
  • 设置方法调用者
  • 设置方法选择器
  • 设置参数
  • 如果有返回值,获取返回值
     

4.invocation代码演示


-(void)invocationInstance{
    //    1.通过方法调用者创建方法签名;此方法是NSObject(或者子类)的方法
    NSMethodSignature *sig = [[self class] instanceMethodSignatureForSelector:@selector(take:andAge:andBlue:)];
    //    2.通过方法签名 生成NSInvocation
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    //    3.对invocation设置 方法调用者
    invocation.target = self;
    //    4.对invocation设置 方法选择器
    invocation.selector = @selector(take:andAge:andBlue:);
    //    5.对invocation设置 参数
    NSString *name = @"张三";
    NSString *age = @"20";
    NSString *color = @"red";
    //注意:设置的参数必须从2开始;因为0和1 已经被self ,_cmd 给占用了
    [invocation setArgument:&name atIndex:2];
    [invocation setArgument:&age atIndex:3];
    [invocation setArgument:&color atIndex:4];
    //    6.执行invocation
    [invocation invoke];
    
    //    7.判断 方法签名 判断是否有返回值
    // 方法签名的返回值类型,下面随便举了2个例子
    const char *sigretun =  sig.methodReturnType;
    //方法签名返回值长度; 如果是字符串返回8,数字返回4,没有返回值返回0;
    NSUInteger siglength = sig.methodReturnLength;
    if (siglength !=0) { //有返回值
        if (strcmp(sigretun, "@") == 0) {
            NSString *returnStr;
            [invocation getReturnValue:&returnStr];
            NSLog(@"字符串返回值:%@",returnStr);
        }else if (strcmp(sigretun, "q")==0){
            NSInteger a = 0;
            [invocation getReturnValue:&a];
            NSLog(@"原始返回值:%zd",a);
            a=100;
            [invocation setReturnValue:&a];
            NSLog(@"新设定的返回值:%zd",a);
        }
    }else{ //没有返回值
        NSLog(@"没有返回值");
    }
    
    //    8.常用方法
    NSUInteger argumentNum = sig.numberOfArguments;
    NSLog(@"%zd",argumentNum); //参数的个数
    for(int i=0;i<argumentNum;i++){

        const char *type = [sig getArgumentTypeAtIndex:i];
        NSLog(@"下标:%d  参数类型:%s",i,type);

    }
    
}

//三个参数的方法
-(void)take:(NSString *)name andAge:(NSString *)age andBlue:(NSString *)color{
    NSLog(@"%@-%@-%@",name,age,color);
//    return 7;
}



 

5.常见方法及属性

  • NSInvocation
//保留参数,它会将所有参数和self 都retain 一遍
-(void)retainArguments;
//判断参数是否存在,调用retainArguments之前,值为NO,调用之后值为YES
@property(readonly)Bool argumentsRetained;
  • NSMethodSignature其他常用方法和属性
//参数个数
@property(readonly)NSUInteger numberOfArguments;
//获取方法的长度
@property(readonly)NSUInteger frameLength;
//是否是单向
-(Bool)isOneWay;
//获取方法返回值的类型
@property(readonly)const char *methodReturnType;
//获取方法返回值的长度
@property(readonly)NSUInteger methodReturnLength;
//获取指定下标的参数类型
-(const char*)getArgumentTypeArIndex:(NSUInteger)idx;
//通过c字符串获得方法签名
+(nullable MethodSignature*)signatureWithObjectCType:(const char*)types;


 

 

 

 


在附上一个实例,解决了ipad 横屏时,进入app 右侧黑屏的问题

//解决横屏启动时,app右侧是黑的问题
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(setStatusBarOrientation:)]){
        SEL selector = NSSelectorFromString(@"setStatusBarOrientation:");
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIApplication instanceMethodSignatureForSelector:selector]];
        UIDeviceOrientation orentation = UIDeviceOrientationPortrait;
        [invocation setSelector:selector];
        [invocation setTarget:[UIApplication sharedApplication]];
        [invocation setArgument:&orentation atIndex:2];
        [invocation invoke];
    }

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值