Cocoa触发方法调用的几种方法

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

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

1.SEL触发

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

[objc] view plain copy

 

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

看了上面代码这下你明白了什么是SEL了吧,平时我们开发当中经常用到的。
有了SEL这样就可以触发方法调用了,

[objc] view plain copy

 

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

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

2. IMP触发

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

[objc] view plain copy

 

  1. IMP theImplementation = [self methodForSelector:theSelector];  

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

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

[objc] view plain copy

 

  1. theImplementation(self, theSelector, 30, 5);  

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

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

3. objc_msgSend方法

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

[objc] view plain copy

 

  1. objc_msgSend(self, @selector(fly));  
  2.   
  3. [self fly];  

4. NSInvocation

NSInvocation相比上面几种方法,可以动态决定传入的参数个数。有了它,我们就可以实现…这样的变参API封装。
说得有点抽像,看代码更清楚:

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

[objc] view plain copy

 

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

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

[objc] view plain copy

 

  1. NSNumber *arg1 = [NSNumber numberWithDouble:15.0];   
  2. NSNumber *arg2 = [NSNumber numberWithDouble:13.0];  
  3.  SEL selector = @selector(addNSNumber:withNumber:);   
  4. NSMethodSignature *sig = [self methodSignatureForSelector:selector];   
  5. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];   
  6. [invocation setTarget:self]; [invocation setSelector:selector];   
  7. [invocation setArgument:(voidvoid *)&arg1 atIndex:2];  
  8.  [invocation setArgument:(voidvoid *)&arg2 atIndex:3];  
  9.  [invocation invoke]; if ([sig methodReturnLength])  
  10.  { [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  新浪微博

原文地址:http://blog.csdn.net/qq_31810357/article/details/50550133

时间: 2024-12-03 04:00:35

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

详解PHP实现异步调用的4种方法_php技巧

浏览器和服务器之间是通过 HTTP 协议进行连接通讯的.这是一种基于请求和响应模型的协议.浏览器通过 URL 向服务器发起请求,Web 服务器接收到请求,执行一段程序,然后做出响应,发送相应的html代码给客户端. 这就有了一个问题,Web 服务器执行一段程序,可能几毫秒就完成,也可能几分钟都完不成.如果程序执行缓慢,用户可能没有耐心等下去,就关闭浏览器了. 而有的时候,我们更本不关心这些耗时的脚本的返回结果,但却还要等他执行完返回,才能继续下一步. 那么有没有什么办法,只是简单的触发调用这些耗

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

代码1:   打印结果:   代码2:   运行结果:     问题: 代码1中super是父类自己调用自己的add()方法,并在add()方法中调用了私有的del()方法,那为什么打印出来的this是子类? 代码2中this是子类去调用了父类继承下来的add()方法,但是为什么还能在add()方法中调用到父类的私有的del()方法?   谁能解释为什么? 欢迎留言.不要说废话! 看懂问题再来讨论为什么!!!!!!  

解决jquery中动态新增的元素节点无法触发事件问题的两种方法_jquery

比如做一个ajax读取留言列表的时候,每条留言后面有个回复按钮,class为"reply",如果你用的是$(".reply").click(function(){ //do something... }),想必后面通过ajax加载进来的列表中的回复按钮,点击事件会失效. 其实最简单的方法就是直接在标签中写onclick="",但是这样写其实是有点low的,最好的方式还是通过给类名绑定一个click事件. 解决jquery中动态新增的元素节点无法触

Asp.net后台调用js 2种方法_实用技巧

1. 用Response.Write方法 代码如下: 复制代码 代码如下: Response.Write("<script type='text/javascript'>alert("XXX");</script>"); 此方法缺陷就是不能调用脚本文件中的自定义的函数,只能调用内部函数,具体调用自定义的函数只能在Response.Write写上函数定 义,比如 复制代码 代码如下: Response.Write("<scrip

Android 开发延时调用的几种方法_Android

  我们在安卓开发中,有时候会遇到需要一个程序推迟一段时间执行,也就是延时执行,比如说App首页显示定格3秒,然后自动跳到登录页的情况,这个怎么做呢?本文参考网上,整理了一下几点,供广大安卓开发者参考,希望对读者有所帮助. 一.开启新线程                            new Thread(new Runnable(){ public void run(){ Thread.sleep(XXXX); handler.sendMessage(); //告诉主线程执行任务 }

SQL Server中避免触发镜像SUSPEND的N种方法_MsSql

背景:我们在使用数据库的过程中,很多时候要追求性能,特别在处理大批量数据的时候更希望快速处理.那么对SQL SERVER而言,数据库实现大批量插入的优化方案,这里特别介绍通过大容量插入的一种方式. 基本原理: 简单恢复模式按最小方式记录大多数大容量操作,对于完整恢复模式下的数据库,大容量导入期间执行的所有行插入操作被完整地记录到事务日志中.如果数据导入量较大,会导致迅速填满事务日志.对于大容量导入操作,按最小方式记录比完整记录更有效,并减少了大容量导入操作填满日志空间的可能性,所以性能会得到极大

SQL Server中避免触发镜像SUSPEND的N种方法

背景: 我们在使用数据库的过程中,很多时候要追求性能,特别在处理大批量数据的时候更希望快速处理.那么对SQL SERVER而言,数据库实现大批量插入的优化方案,这里特别介绍通过大容量插入的一种方式. 基本原理: 简单恢复模式按最小方式记录大多数大容量操作,对于完整恢复模式下的数据库,大容量导入期间执行的所有行插入操作被完整地记录到事务日志中.如果数据导入量较大,会导致迅速填满事务日志.对于大容量导入操作,按最小方式记录比完整记录更有效,并减少了大容量导入操作填满日志空间的可能性,所以性能会得到极

Android 开发延时调用的几种方法

我们在安卓开发中,有时候会遇到需要一个程序推迟一段时间执行,也就是延时执行,比如说App首页显示定格3秒,然后自动跳到登录页的情况,这个怎么做呢?本文参考网上,整理了一下几点,供广大安卓开发者参考,希望对读者有所帮助. 一.开启新线程 new Thread(new Runnable(){ public void run(){ Thread.sleep(XXXX); handler.sendMessage(); //告诉主线程执行任务 } }).start 二.利用定时器 imerTask tas

能不能在DLL重写某个OCX内的方法,调用OCX时此方法时就自动调入DLL内函数??

问题描述 行不行呢?100救助? 解决方案 解决方案二:没有弄过,是不是需要全局钩子或者DLL注入之类的东东,那不是做病毒了么?不懂