在objc中,选择器(selector)不是函数指针。选择器是一个唯一的整数,在由objc运行时存储的方法查找表中映射到一个字符串。在上面的例子中,你的方法名将是
myObjCSelector:
,要获取它的唯一选择器,你需要键入
@selector(myObjCSelector:)
。然而,这对你来说没有任何用处,因为它并不代表一个特定的函数实现。
你要找的是IMP,请参考
这个SO问题。
编辑 2: IMP myObjCSelectorPointer = (void (*)(id,SEL,int*))[self methodForSelector:@selector(myObjCSelector:)];
然后您可以使用以下方法调用该方法
myObjCSelectorPointer(self,@selector(myObjCSelector:),myIntArray);
然而,这意味着你需要确保在c函数调用passObjCSelectorPointerToCContext时将self指针添加进去。因此,它应该看起来像这样:
passObjCSelectorPointerToCContext(cContextReference, self, myObjCSelectorPointer);
当从包含该方法的对象内部调用时。
需要注意的是,几乎从不使用 IMP 是正确的技术选择。应该尽量坚持纯 Obj-C。由于 Obj-C 使用临时缓存,因此在第一次调用消息后,Obj-C 是相当高效的。
编辑1:
了解 objc 为什么以这种方式工作非常有用。苹果文档提供了深入的
解释。但简短的解释如下:当您向对象发送消息,例如
[myobject somemethod]
,编译器不会立即知道要调用哪个特定实现的 somemethod,因为可能有多个类具有多个重写版本的 somemethod。所有这些方法都具有相同的选择器,而与其参数和返回值无关,因此对于 somemethod 的哪个实现的决策被推迟到程序运行时执行
[myobject somemethod]
被编译器转换为 C 函数调用:
objc_msgSend(myobject, @selector(somemethod))
这是一个特殊的函数,它会搜索每个
myobject
类的布局,以查看该类是否知道如何响应
somemethod
消息。如果不知道,它会继续搜索该类的父类,直到根类。如果没有任何类能够响应
somemethod
,则
NSObject
定义了一个名为forward的私有方法,用于接收所有未知的消息。
假设某个类能够响应somemethod
消息,则它还将具有指向该方法实际实现的类型为IMP的特定指针。此时将调用该方法。
这个过程比我描述的要复杂得多,但这个概述应该足以帮助您理解选择器的目的。
最后一点是,方法名被映射到唯一整数的原因是因为运行时不必浪费时间进行字符串比较。