在objective-C运行时,为什么method_getNumberOfArguments返回的结果比选择器所暗示的多两个?
例如,为什么@selector(initWithPrice:color :)返回4?
答案 0 :(得分:6)
好的。只是为了直接设置记录,是的,任何objective-c方法的前两个参数都是self
和_cmd
,总是按顺序排列。
然而,更有趣的主题是为什么到这种情况。要做到这一点,我们首先要看看objc的历史。不用多说,让我们开始吧。
回到1983年,布拉德考克斯,上帝' objective-c希望在 C之上创建一个面向对象的基于运行时的语言,以实现跨平台的良好性能和灵活性。结果,第一个Objective-C'编译器'只是简单的Objective-C源预处理器转换为它们的C-runtime等价物,然后用平台特定的C编译器工具编译。但是,C不是为对象设计的,而这是Objective-C必须克服的最基本的东西。虽然C是一种强大而灵活的语言,但运行时支持是其中一个重要的弊端。
在Objective-C的早期设计阶段,决定对象将是一个纯粹的基于堆的指针设计,这样它们就可以在任何函数之间传递而没有奇怪的复制语义等等(这改变了一点Obj-C ++和ARC,但这个帖子的范围太广了),并且每个方法都应该是自我意识的(正如bbum指出的那样,它是一个优化的使用与原始函数调用相同的堆栈帧,以便理论上可以将多个方法名映射到同一个选择器,如下所示:
// this is a completely valid objc 1.0 method declaration
void *nameOrAge(id self, SEL _cmd) {
if (_cmd == @selector(name)) {
return "Richard";
}
if (_cmd == @selector(age)) {
return (void *) (intptr_t) 16;
}
return NULL;
}
然后,该函数可以在理论上映射到两个选择器name
和age
,并根据调用哪个选择器执行条件代码。在一般的Objective-C代码中,这并不是什么大不了的事,因为现在将ARC映射到选择器是很困难的,因为演员等等,但语言从那时起已经发展了很多。
希望这有助于您理解两个“隐形”背后的为什么。 Objective-C方法的参数,第一个是被调用的对象,第二个是在该对象上调用的方法。
答案 1 :(得分:2)
前两个参数是隐藏的参数self和_cmd。