每日更新关注:http://weibo.com/hanjunqiang 
新浪微博

1.SEL触发

SEL就是selector的缩写,它表示Cocoa中的方法选择器,不明白?那请仔细了解Objective_C的运行时机制与Cocoa底层思想。

SEL theSelector = @selector(methodWithInt:andInt:);

看了上面代码这下你明白了什么是SEL了吧,平时我们开发当中经常用到的。

有了SEL这样就可以触发方法调用了,

[self performSelector:theSelector]
[self performSelector:@selector(methodWithInt:andInt:)];

上面两句代码是同一个道理。

2. IMP触发

IMP其实就是一个函数指针的概念,就可以这么简单理解。

IMP theImplementation = [self methodForSelector:theSelector];

上面这句代码就是获取methodWithInt:andInt:这个方法的地址。

有了这个函数指针后,我们就可以触发方法:

theImplementation(self, theSelector, 30, 5);

第一个是对象,第二个SEL, 后面的传入的参数。

每日更新关注:http://weibo.com/hanjunqiang 
新浪微博

3. objc_msgSend方法

这是Objc运行时的一个C方法,我们先看一个示列:

objc_msgSend(self, @selector(fly));

[self fly];

4. NSInvocation

NSInvocation相比上面几种方法,可以动态决定传入的参数个数。有了它,我们就可以实现…这样的变参API封装。

说得有点抽像,看代码更清楚:

假如我们实现了一个两个数相加的方法,

-(void)addNSNumber:(NSNumber *)first withNumber:(NSNumber *)second

我们可以用下面的方法来触发这个方法,并获取返回值。

NSNumber *arg1 = [NSNumber numberWithDouble:15.0];
NSNumber *arg2 = [NSNumber numberWithDouble:13.0];
 SEL selector = @selector(addNSNumber:withNumber:);
NSMethodSignature *sig = [self methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setTarget:self]; [invocation setSelector:selector];
[invocation setArgument:(void *)&arg1 atIndex:2];
 [invocation setArgument:(void *)&arg2 atIndex:3];
 [invocation invoke]; if ([sig methodReturnLength])
 { [invocation getReturnValue:&retval]; return retval; } return nil; }

代码很容易理解,我也不多做解释,有不明白的请留言。

每日更新关注:http://weibo.com/hanjunqiang 
新浪微博

下面是变参封装, 写了两个NSObject的Extension(Category):

 
+ (NSInvocation *)createInvocationOnTarget:(id)target selector:(SEL)selector {
  return [NSObject createInvocationOnTarget:target selector:selector withArguments:nil];
}

+ (NSInvocation *)createInvocationOnTarget:(id)target selector:(SEL)selector withArguments:(id)arg1, ... {
  NSMethodSignature *sig = [target methodSignatureForSelector:selector];
  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];

  [invocation setTarget:target];
  [invocation setSelector:selector];

  if(arg1) {
      va_list args;
      va_start(args, arg1);

      [invocation setArgument:(void *)&arg1 atIndex:2];

      id obj;
      int ct = 3;

      while( obj = va_arg(args, id) ) {
          NSLog(@"%@", obj);
          [invocation setArgument:(void *)&obj atIndex:ct];

          ct++;
      }

      va_end(args);
  }

  return invocation;
}

调用方法:

 
NSInvocation *invocation = [NSObject createInvocationOnTarget:mathInstance selector:selector withArguments: arg1, arg2, nil]; 

[invocation invoke];
[invocation getReturnValue:&retval];

return retval;

每日更新关注:http://weibo.com/hanjunqiang 
新浪微博

Cocoa触发方法调用的几种方法的更多相关文章

  1. struts调用的几种方法

    在Struts2中方法调用概括起来主要有三种形式 第一种方式:指定method属性 <action name="student" class="com.itmyho ...

  2. Struts2方法调用的三种方式

    在Struts2中方法调用概括起来主要有三种形式 第一种方式:指定method属性 <action name="student" class="com.itmyho ...

  3. Struts2方法调用的三种方式(有新的!调用方法的说明)

    在Struts2中方法调用概括起来主要有三种形式 第一种方式:指定method属性 <action name="heroAction" class="com.ABC ...

  4. 第164天:js方法调用的四种模式

    js方法调用的四种模式 1.方法调用模式 function Persion() { var name1 = "itcast", age1 = 19, show1 = functio ...

  5. QT下实现对Linux Shell调用的几种方法

    使用QProcess QThread ============================================ #include <QProcess>int main(){ ...

  6. 【java】子类可以通过调用父类的public方法调用父类的private方法,为什么?

    代码1: 打印结果: 代码2: 运行结果: 问题: 代码1中super是父类自己调用自己的add()方法,并在add()方法中调用了私有的del()方法,那为什么打印出来的this是子类? 代码2中t ...

  7. vue中触发键盘事件的两种方法和如何自定义键位事件,完整代码!

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Android延时执行调用的几种方法

    一.开启新线程 new Thread(new Runnable(){        public void run(){            Thread.sleep(XXXX);          ...

  9. php 递归调用又一种方法

     public static function encodeXml($data){        $attr = $xml = "";        foreach($data a ...

随机推荐

  1. WebStorm 快捷键一览

    查找/代替 快捷键 说明 ctrl+shift+N 通过文件名快速查找工程内的文件(必记) ctrl+shift+alt+N 通过一个字符快速查找位置(必记) ctrl+F 在文件内快速查找代码 F3 ...

  2. Cisco banner 登陆消息提示设置命令详解

    从法律角度来看,登陆消息非常重要.当入侵者进入网络而没有受到适当的警告时,他们有可能赢得官司.在放置登陆消息之前应让律师检查下,永远不要使用"欢迎"等问候语,以免被误解为邀请大家使 ...

  3. String 类

    一.String类String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象.java把String类声明的final类,不能有类.String类对象创建 ...

  4. 去掉textarea和input在ios下默认出现的圆角

    -webkit-appearance:none;/*清除ios默认圆角*/ border-radius:0;

  5. C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节

    C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节 1.Qt概述 1.1 什么是Qt Qt是一个跨平台的C++图形用户界面应用程序框架.它为应用程序开发者提供建立艺术级图形界面 ...

  6. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令

    ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利. 这次来建立一个示例,演示一下如何在脚本中自定义协程中断指令 Unity中的 ...

  7. 深入理解Lambda函数及其用法

    Lambda函数又称匿名函数,匿名函数就是没有名字的函数,函数没有名字也行?当然可以啦.有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可. 先来看个简单lambda函数 ...

  8. webpack4新建一个项目

    Create a new directory mkdir webpack-4-quickstart Initialize a package.json by running: npm init -y ...

  9. 利用百度接口进行人脸识别并保存人脸jpg文件

    利用百度接口进行人脸识别,根据返回的人脸location用opencv切割保存. # coding : UTF-8 from aip import AipFace import cv2 import ...

  10. Kafka系列之-Kafka Protocol实例分析

    本文基于A Guide To The Kafka Protocol文档,以及Spark Streaming中实现的org.apache.spark.streaming.kafka.KafkaClust ...