Objective-C中的选择器?


122

首先,我不确定我是否真的了解选择器。据我了解,它是方法的名称,您可以将其分配给类型为'SEL'的类,然后运行诸如responseToSelector之类的方法,以查看接收方是否实现了该方法。有人可以提供更好的解释吗?

其次,到目前为止,我有以下代码:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

但是,尽管thing显然是一种NSString,并且应该响应lowercaseString,但我无法获得“ respondsToSelector”条件来返回“ YES” ...


您想阅读Apple开发者网站上的Selector描述:Selectors
lothar

14
斯坦福课程CS193P作业1B?我在这里有完全一样的问题!:)
Corstian Boerman

Answers:


181

您必须非常注意方法名称。在这种情况下,方法名称仅为“ lowercaseString”,而不是“ lowercaseString:”(请注意不存在冒号)。这就是为什么您要NO返回的原因,因为NSString对象响应lowercaseString消息而不是lowercaseString:消息。

您怎么知道何时添加冒号?如果在调用消息名称时添加了一个冒号,则可以在消息名称中添加一个冒号,如果使用一个参数则会发生这种情况。如果它接受零个参数(与一样lowercaseString),则没有冒号。如果需要多个参数,则必须添加额外的参数名称及其冒号,如所示compare:options:range:locale:

您还可以查看文档并注意尾随冒号的存在或不存在。


12

选择器是直接在已编译代码中引用方法的有效方法-编译器实际上是将值分配给SEL的工具。

其他人已经覆盖了q的第二部分,最后的“:”与您要查找的特征匹配不同的签名(在这种情况下,该签名不存在)。


10

那是因为你想要@selector(lowercaseString)而不是@selector(lowercaseString:)。有一个细微的差异:第二个参数隐含一个参数(注意末尾的冒号),但- [NSString lowercaseString]不包含参数。


5

在这种情况下,选择器的名称错误。这里的冒号是方法签名的一部分;这意味着该方法采用一个参数。我相信你想要

SEL sel = @selector(lowercaseString);


1

不要将冒号视为函数名称的一部分,而应将其视为分隔符,如果您没有要分隔的任何内容(该函数没有任何价值),则不需要它。

我不知道为什么,但是所有这些面向对象的知识对于苹果开发人员来说都是陌生的。我强烈建议抓住Visual Studio Express并尝试使用它。并不是因为一个要比另一个好,而是它是研究设计问题和思维方式的好方法。

喜欢

introspection = reflection
+ before functions/properties = static
- = instance level

最好以不同的方式看待问题,而编程是最终的难题。


0

根据我对Apple文档的理解,选择器代表您要调用的方法的名称。关于选择器的好处是,可以在要调用的确切方法有所不同的情况下使用它们。作为一个简单的示例,您可以执行以下操作:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];

0

根据苹果文档:https : //developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

选择器是用于选择要为对象执行的方法的名称,或者是唯一的标识符,用于在编译源代码时替换该名称。选择器本身不会执行任何操作。它仅标识一种方法。使选择器方法名称不同于纯字符串的唯一事情是编译器确保选择器是唯一的。选择器之所以有用,是因为它(与运行时结合使用)就像一个动态函数指针,对于给定的名称,它会自动指向适用于所使用的任何类的方法的实现。假设您有一个用于方法运行的选择器,以及Dog,Athlete和ComputerSimulation类(它们各自实现了方法运行)。

示例:(lldb)断点--set选择器viewDidLoad

这将在应用程序中的所有viewDidLoad实现上设置一个断点。因此,选择器是方法的全局标识符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.