Objective-C中的选择器是另一种向对象发送消息的方式吗?

时间:2010-08-22 20:06:47

标签: objective-c selector objective-c-runtime

Objective-C中的选择器是另一种向对象发送消息的方式吗?我真的不明白为什么或如何使用它们。

5 个答案:

答案 0 :(得分:21)

当您想要定义回调机制时,通常会使用选择器。 Cocoa中选择器最常见的用例是控件,如按钮。 UIButton非常通用,因此不知道按下按钮时会发生什么。在使用之前,您需要告诉它按下按钮时应该运行什么方法。这样做如下:

[myButton addTarget:self
             action:@selector(myButtonWasPressed)
   forControlEvents:UIControlEventTouchUpInside];

- (void)myButtonWasPressed {
    // Do something about it
}

然后,当按下按钮时,按钮将调用我们传递它的目标上的选择器。使用此机制,每次希望它调用您自己的代码时,您都不需要子类化按钮。相反,UIButton本身有一个通用的机制来分派您选择的任何代码。 (好的,从技术上讲,它是提供调度机制的超类UIControl。)

答案 1 :(得分:16)

它们不是向对象发送消息的另一种方式,它们是唯一的方式。例如,在[myView setValue:@"foo"]中,setValue:是一个选择器。 (编写相同内容的另一种不太方便的方法是objc_msgSend(myView, @selector(setValue:), @"foo")。)

正如Ian Henry所说,您可以使用SEL值在运行时而不是编译时选择一个选择器。这是Cocoa的一项基本技术;用户界面通常使用目标/动作绑定连接到控制器,其中目标是对象,动作是选择器。通常你可以在笔尖中设置它,但你也可以在代码中进行设置:

[myButton setTarget:myController];
[myButton setAction:@selector(buttonClicked:)]; // Clicking the button will now call [myController buttonClick:myButton].

答案 2 :(得分:4)

您可以将选择器存储为变量,稍后或在不同的上下文中调用它们。例如,您可以告诉对象在特定时间或不同线程上执行选择器。您还可以根据数据选择要执行的选择器,这是界面构建器和核心数据的工作方式。

答案 3 :(得分:3)

最基本的,是的,但您可以在运行时更改消息。例如:

SEL a = [selectorFactory getSelector];
[someOtherObject performSelector:a];

然后在selectorFactory.getSelector

if(foo == 1)
    return @selector(thisSelector);
else
    return @selector(thatSelector);

来自C#或其他类似语言,您可以使用它来(松散地)模拟事件比使用NSNotification更容易。例如,您可以创建一个包含两个ivars targetselector的按钮类,并让按钮在单击时执行目标选择器(例如)。

尽管如此,选择者还有很多。在这里阅读更多关于他们的信息:

http://developer.apple.com/mac/library/documentation/cocoa/conceptual/objectivec/articles/ocSelectors.html

答案 4 :(得分:0)

- 来自Apple Developer Library -

选择器是用于选择要为对象执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。选择器本身不做任何事情。它只是识别一种方法。使选择器方法名称与普通字符串不同的唯一因素是编译器确保选择器是唯一的。使选择器有用的原因是(与运行时一起)它就像一个动态函数指针,对于给定的名称,它自动指向适用于它所使用的任何类的方法的实现。假设你有一个方法运行的选择器,以及类Dog,Athlete和ComputerSimulation(每个都实现了一个方法运行)。选择器可以与每个类的实例一起使用来调用其run方法 - 即使每个类的实现可能不同。