124

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

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

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,并且应该响应小写字符串,我也无法让“respondsToSelector”有条件地返回“YES”......

4

8 回答 8

183

您必须非常小心方法名称。在这种情况下,方法名称只是“ lowercaseString”,而不是“ lowercaseString:”(注意没有冒号)。这就是你被NO退回的原因,因为NSString对象响应lowercaseString消息而不是lowercaseString:消息。

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

您还可以查看文档并注意是否存在尾随冒号。

于 2009-04-10T19:42:32.397 回答
12

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

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

于 2009-04-10T19:50:20.770 回答
10

那是因为你想要@selector(lowercaseString),而不是@selector(lowercaseString:)。有一个微妙的区别:第二个暗示一个参数(注意最后的冒号),但- [NSString lowercaseString]不带参数。

于 2009-04-10T19:44:13.077 回答
6

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

SEL sel = @selector(lowercaseString);
于 2009-04-10T19:41:58.590 回答
3

NSString 的方法是lowercaseString(0 个参数),而不是lowercaseString:(1 个参数)。

于 2009-04-10T19:42:42.097 回答
1

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

我不知道为什么,但所有这些面向对象的东西对于 Apple 开发人员来说似乎都是陌生的。我强烈建议使用 Visual Studio Express 并使用它。不是因为一个比另一个更好,只是它是看待设计问题和思维方式的好方法。

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

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

于 2009-04-11T12:05:47.133 回答
0

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

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
于 2014-10-16T23:30:27.250 回答
0

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

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

Example: (lldb) breakpoint --set selector viewDidLoad

This will set a breakpoint on all viewDidLoad implementations in your app. So selector is kind of a global identifier for a method.

于 2018-08-10T10:30:12.143 回答