编程学习biancheng.45soft.com 本站提供了各种在线教程和资料,供大家学习与参考.
编程学习
当前位置: 主页 > Objective-C > 高级消息机制 > Objective-C 高级消息机制 什么是IMP

Objective-C 高级消息机制 什么是IMP

当一个消息被发送出去后,Objective-C的运行时会查找接收消息对象的方法实现,如果对象本身没有方法实现,那么运行时会顺着类继承的层级关系,逐级向上找遍接收对象的所有父类直到找到为止或者最终也找不到为止。这项工作非常耗时,当然,运行时在第一次寻找方法实现的时候,如果找到了该方法的实现,就会将它放进缓存中,下次再访问该方法就会快上许多。然而,即便是访问缓存中的数据,也是需要查找并花费一定的时间。有一些应用程序非常重视性能,怎么办呢?有办法,你可以自己来实现运行时的功能,自己去找到方法实现。从本质上说,方法实现是一个函数地址的指针,编译器提供了方法实现的数据结构并存储起来,在运行时才可以被找到。请看如下代码:

SEL getObjSelector = @selector(getObjectAtIndex:);
// 获取到NSArray类的对象’taskArray’的方法实现,将其存入SEL类型变量getObjSelector
IMP getObjImp = [taskArray methodForSelector: getObjSelector];
// 通过getObjSelector这个selector获取到getObjectAtIndex:方法的指针,将其存入IMP类型的变量getObjImp中
id obj = (getObjImp)( taskArray, getObjSelector, i );//通过C语言中标准的利用函数地址调用函数的表达式来调用taskArray对象的getObjImp方法,进行getObjectAtIndex:方法的调用。

上述代码,就是一个通过方法地址直接调用方法的具体例子。那么其中IMP(ImplementationPointer)类型就是函数指针,它的类型定义是 :

typedef id (*IMP)(id, SEL, ...);

我们可以看到,IMP类型定义的方法的返回值是id,但不是所有的方法返回的都是id类型,当然对于那些返回不是id类型的方法,你还是可以用函数指针的方法去调用他们,不过你需要自己去实现一些代码,例如这里有一个方法返回值是double:

double (*squareFunc)( id, SEL, double );//定义一个函数指针变量squareFunc
double result;
//通过selector获取方法squareOf:地址并强制转换到double (*)( id, SEL, double )类型的地址
squareFunc = (double (*)( id, SEL, double ))[mathObj methodForSelector: @selector(squareOf:)];
result = squareFunc(mathObj, @selector(squareOf:), 4);//通过函数指针变量调用函数。

如上代码所示,除了返回值是id类型之外,你都需要自己去实现一个函数指针变量。另外第一行中的参数double并非必须写明,你也可以这么写"double (*squareFunc)( id, SEL, ... )"。


你要清醒的认识到,除非是很多次的调用某方法,你用函数指针去调用才比较值得,而且你这个方法里的代码量相对来说要小于消息发送的实现代码量。



编程学习 Objective-C 高级消息机制 什么是IMP 转载请保留此行.谢谢.

Objective-C