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

简介: 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 1.SEL触发 SEL就是selector的缩写,它表示Cocoa中的方法选择器,不明白?那请仔细了解Objective_C的运行时机制与Cocoa底层思想。

每日更新关注: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  新浪微博

目录
相关文章
|
6月前
layoutSubviews 调用时机
layoutSubviews 调用时机
18 0
|
Java C++
JNI全局回调java方法
JNI全局回调java方法
|
存储 JavaScript Java
【代码篇】事件监听函数的内存泄漏,都给我退散吧!
内存泄漏是个很严肃的问题,可是迄今也没有一个非常有效的排查方案,本方案就是针对性的单点突破。 工作中,我们会对window, DOM节点,WebSoket, 或者单纯的事件中心等注册事件监听函数, 添加了,没有移除,就会导致内存泄漏,如何预警,收集,排查这种问题呢?
184 0
【代码篇】事件监听函数的内存泄漏,都给我退散吧!
|
Android开发
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取要注入事件的 View 对象 | 通过反射获取 View 组件的事件设置方法 )
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 获取要注入事件的 View 对象 | 通过反射获取 View 组件的事件设置方法 )
219 0
|
Java Android开发 开发者
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )
154 0
构建 View 时可能用到的代理函数调用顺序
  很多时候,要记住iPhone试图加载的life-cycle对应的代理函数是有点头疼的,特别是用Interface Builder构建界面的情况下。这给如何找到最佳的位置来添加自定义的视图绘画/初始化/配置成为了一个对于新手来说的难题。
633 0
|
图形学
Unity 事件函数的执行顺序
在 Unity 脚本中,有许多事件函数在脚本执行时按预定的顺序执行。这个执行顺序如下所述: 首个场景加载这些函数在场景开始时调用(对于场景中的每个对象调用一次)。 Awake:在所有 Start 函数之前,以及 prefab 实例化之后调用。
2173 0