OC动态调用方法

获取Class的三种方式:

  1/ Class clazz_1 = NSStringFromClass(@"ClassName");

  2/ Class clazz_2 = [ClassName class];

  3/ Class clazz_3 = [ClassInstance class];

  可以直接使用clazz_x来创建对应的类对象: [[clazz_1 alloc] init];

获取协议(protocol)名

  Protocol *po = [Protocol NSProtocolFromString:@"protocolName"];

判断是否实现了某个协议:

  [classInstance conformsToProtocol:protocolName];


获取SEL对象:

  1/ SEL sel = [SEL NSSelectorFromString:@"methodName"];

  2/ SEL sel = @selector(methodFullName);


判断某个对象是否可以执行某个方法

  [classInstance respondsToSelector:sel];


动态调用方法的两种方式

  1/ [obj performsToSelector:sel];

  2/ objc_msgSend(receiver, selector, ...);

    2.1/ 需要返回float, 改用objc_msgSend_fpret(receiver, selector, ...);

    2.2/ 需要返回结构体, 改用objc_msgSend_stret(receiver, selector, ...);

    这个方法需要 #import <objc/message.h>


通过函数指针来调用方法

  OC中IMP的定义:

  #if !OBJC_OLD_DISPATCH_PROTOTYPES
  typedef void (*IMP)(void /* id, SEL, ... */ );
  #else
  typedef id (*IMP)(id, SEL, ...);
  #endif

  解释:
    1/ IMP是一个指向方法/函数的实现的指针. 因为OC是完全兼容C的, 第一种定义是对C,第二种是对OC的(因为OC有方法, 方法需要对象来调用)

    2/ OBJC_OLD_DISPATCH_PROTOTYPES(分发函数原型). 有啥用呢? 上面说了OC中引入了方法的概念, 而C是没有的. 方法需要对象调用,而函数不用对象. 所以就需要一个指标来确定IMP指向的是函数还是方法, 这个宏就是来做这件事的. 当将返回的IMP强转为OC的指向方法的指针, 这个宏保持为1, 当我们将返回的IMP保持默认时, 它为0,意为指向C的函数.

 

  OC中使用IMP调用方法:

	    TestClass *testClass = [[TestClass alloc] init];

	    // testWithChar: 是TestClass的一个方法
	    SEL sel = NSSelectorFromString(@"testWithChar:");

	    int (*imp)(id, SEL, char) ;

	    // 将返回的IMP指针强转为OC方法的指针类型 
	    // OC的方法指针类型, 一定要有id(调用者), SEL(调用者要调用的方法名, 参数列表)
	    imp = (int (*)(id, SEL, char))[testClass methodForSelector:sel];

	    imp(testClass, sel, 'a');

  

posted on 2017-12-12 10:21  KeplerAir  阅读(1741)  评论(0编辑  收藏  举报