Objective-C 中的选择器是向对象发送消息的另一种方式吗?我真的不明白为什么或如何使用它们。
5 回答
当您要定义回调机制时,通常会使用选择器。Cocoa 中选择器最常见的用例是控件,例如按钮。AUIButton
非常通用,因此不知道按下按钮时会发生什么。在你可以使用之前,你需要告诉它按下按钮时应该运行什么方法。这是按如下方式完成的:
[myButton addTarget:self
action:@selector(myButtonWasPressed)
forControlEvents:UIControlEventTouchUpInside];
- (void)myButtonWasPressed {
// Do something about it
}
然后,当按下按钮时,按钮将调用我们传递给它的目标上的选择器。使用这种机制,您无需在每次希望按钮调用您自己的代码时都对它进行子类化。取而代之的是,UIButton
它本身具有一种通用机制,可以分派给您选择的任何代码。(好吧,从技术上讲,它是UIControl
提供调度机制的超类。)
它们不是向对象发送消息的另一种方式,它们是唯一的方式。例如, in[myView setValue:@"foo"]
是setValue:
一个选择器。(另一种不太方便的写同一件事的方法是objc_msgSend(myView, @selector(setValue:), @"foo")
。)
正如 Ian Henry 所说,您可以SEL
在运行时而不是编译时使用值来选择选择器。这是 Cocoa 中的一项基本技术;用户界面通常使用目标/动作绑定连接到控制器,其中目标是对象,动作是选择器。通常您在 nib 中进行设置,但您也可以在代码中进行设置:
[myButton setTarget:myController];
[myButton setAction:@selector(buttonClicked:)]; // Clicking the button will now call [myController buttonClick:myButton].
您可以将选择器存储为变量,并在以后或在不同的上下文中调用它们。例如,您可以告诉对象在特定时间或在不同的线程上执行选择器。您还可以根据数据选择要执行的选择器,这就是界面构建器和核心数据的工作方式。
最基本的是,是的,但是您可以在运行时更改消息。例如:
SEL a = [selectorFactory getSelector];
[someOtherObject performSelector:a];
然后在selectorFactory.getSelector
:
if(foo == 1)
return @selector(thisSelector);
else
return @selector(thatSelector);
来自C#
或其他类似语言,您可以使用它来(松散地)模拟事件,而不是使用NSNotification
s。例如,您可以创建一个包含两个 ivarstarget
和的按钮类selector
,并让按钮在单击时在目标上执行选择器(例如)。
不过,选择器的功能远不止这些。在此处阅读有关它们的更多信息:
--来自苹果开发者库 --
选择器是用于选择要为对象执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。选择器本身不做任何事情。它只是标识一种方法。使选择器方法名称与纯字符串不同的唯一原因是编译器确保选择器是唯一的。使选择器有用的是(与运行时一起)它就像一个动态函数指针,对于给定的名称,它会自动指向适用于与它一起使用的任何类的方法的实现。假设您有一个用于方法 run 的选择器,以及 Dog、Athlete 和 ComputerSimulation 类(每个都实现了一个方法 run)。