为什么method_getNumberOfArguments返回的结果比选择器所暗示的多两个?

时间:2012-12-23 12:56:34

标签: objective-c objective-c-runtime

在objective-C运行时,为什么method_getNumberOfArguments返回的结果比选择器所暗示的多两个?

例如,为什么@selector(initWithPrice:color :)返回4?

2 个答案:

答案 0 :(得分:6)

TL; DR

好的。只是为了直接设置记录,是的,任何objective-c方法的前两个参数都是self_cmd,总是按顺序排列。

Objective-C的简要历史

然而,更有趣的主题是为什么到这种情况。要做到这一点,我们首先要看看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;
}

然后,该函数可以在理论上映射到两个选择器nameage,并根据调用哪个选择器执行条件代码。在一般的Objective-C代码中,这并不是什么大不了的事,因为现在将ARC映射到选择器是很困难的,因为演员等等,但语言从那时起已经发展了很多。

希望这有助于您理解两个“隐形”背后的为什么。 Objective-C方法的参数,第一个是被调用的对象,第二个是在该对象上调用的方法。

答案 1 :(得分:2)

前两个参数是隐藏的参数self和_cmd。