获取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
通过函数指针来调用方法
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');