导语
今天在编码的时候,无意间看到了- (IMP)methodForSelector函数,让我联想到平时经常用的+ (IMP)instanceMethodForSelector函数。这两个函数从字面意思来看很相近,但是既然同时存在,二者一定存在区别。于是,结合开发文档和代码测试,进行了一些探索。
+ (IMP)instanceMethodForSelector:(SEL)aSelector
功能概述:根据指定的sSelector,遍历类的实例方法列表,返回对应的函数指针。
有两个地方需要注意:
一、这是一个类函数,调用者是一个Class;
二、函数返回结果的类型是实例函数指针,而非类函数指针。
代码测试:
@interface TestObject : NSObject
@end
@implementation TestObject
- (void)testFun
{
}
int main(int argc, const char * argv[])
{
IMP p = [TestObject instanceMethodForSelector:@selector(testFun)];
NSLog(@"%p " , p);
return 0;
}
输出结果:
2015-12-21 16:17:02.217 TestProject[2916:166056] 0x100000ad0
猜想:该函数内部实现过程中创建了一个实例对象,然后遍历实例对象的函数列表,搜索指定的函数名对应的函数指针。
- (IMP)methodForSelector:(SEL)aSelector
功能概述:根据指定的sSelector,返回调用者函数列表中对应的函数指针。
有两个地方需要注意:
一、这是一个实例对象函数,调用者可以是实例对象也可以是类对象(在Object C中,类本身也是对象)
二、函数返回结果的类型可能是实例函数指针,也可能是类函数指针。
代码测试:
int main(int argc, const char * argv[])
{
TestObject obj = [TestObject new];
IMP pObj = [obj methodForSelector:@selector(testFun)];
IMP pClass = [TestObject methodForSelector:@selector(testFun)];
NSLog(@"%p" , pObj);
NSLog(@"%p" , pClass);
return 0;
}
输出结果:
2015-12-21 16:39:12.711 TestProject[3002:179046] 0x100000ad0
2015-12-21 16:39:12.713 TestProject[3002:179046] 0x7fff8878bd40
结论:根据上面的输出结果,可以看出实例对象调用- (IMP)methodForSelector与类调用+ (IMP)instanceMethodForSelector输出结果是一致的,都是实例对象的函数指针;而类对象调用- (IMP)methodForSelector输出结果则是类本身的类函数指针。
综述:这两个函数除了类型上的区别之外,- (IMP)methodForSelector函数的使用范围更广一些,既可以获得实例对象函数指针,又能获去类对象函数指针。此外,+ (IMP)instanceMethodForSelector更像是对- (IMP)methodForSelector的一次封装,用来更便捷地获取实例对象的函数指针。