[英]Selectors in Objective-C?
首先,我不确定我是否真的理解选择器是什么。 根据我的理解,它是一个方法的名称,您可以将它分配给一个类型为“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”......
您必须非常注意方法名称。 在这种情况下,方法名称只是“ lowercaseString
”,而不是“ lowercaseString:
”(注意没有冒号)。 这就是为什么您NO
返回NO
的原因,因为NSString
对象响应lowercaseString
消息而不是lowercaseString:
消息。
你怎么知道什么时候加冒号? 如果在调用消息时添加冒号,则在消息名称中添加一个冒号,如果它接受一个参数就会发生这种情况。 如果它接受零个参数(就像lowercaseString
的情况),则没有冒号。 如果需要多个参数,则必须添加额外的参数名称及其冒号,如compare:options:range:locale:
。
您还可以查看文档并注意尾随冒号的存在与否。
选择器是直接在编译代码中引用方法的有效方式——编译器实际上是将值分配给 SEL。
其他人已经涵盖了您的 q 的第二部分,末尾的 ':' 匹配的签名与您要查找的签名不同(在这种情况下,该签名不存在)。
那是因为您想要@selector(lowercaseString)
,而不是@selector(lowercaseString:)
。 有一个细微的区别:第二个意味着一个参数(注意末尾的冒号),但是- [NSString lowercaseString]
不接受参数。
在这种情况下,选择器的名称是错误的。 这里的冒号是方法签名的一部分; 这意味着该方法采用一个参数。 我相信你想要
SEL sel = @selector(lowercaseString);
NSString 的方法是lowercaseString
(0 个参数),而不是lowercaseString:
(1 个参数)。
不要将冒号视为函数名称的一部分,而是将其视为分隔符,如果您没有任何要分隔的内容(该函数没有值),那么您就不需要它。
我不知道为什么,但所有这些面向对象的东西对 Apple 开发人员来说似乎都是陌生的。 我强烈建议抓住 Visual Studio Express 并使用它。 不是因为一个比另一个更好,只是它是一种看待设计问题和思维方式的好方法。
像
introspection = reflection
+ before functions/properties = static
- = instance level
以不同的方式看待问题总是好的,而编程是终极难题。
根据我对 Apple 文档的理解,选择器表示您要调用的方法的名称。 选择器的好处是您可以在要调用的确切方法发生变化的情况下使用它们。 作为一个简单的例子,您可以执行以下操作:
SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
根据苹果文档: https : //developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html
选择器是用于为对象选择要执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。 选择器本身不做任何事情。 它只是标识一个方法。 唯一使选择器方法名称与普通字符串不同的是编译器确保选择器是唯一的。 选择器的有用之处在于(结合运行时)它就像一个动态函数指针,对于给定的名称,它自动指向适用于它所使用的任何类的方法的实现。 假设您有一个用于方法 run 的选择器,以及类 Dog、Athlete 和 ComputerSimulation(每个类都实现了一个方法 run)。 选择器可以与每个类的实例一起使用以调用其 run 方法——即使每个类的实现可能不同。
示例:(lldb) 断点 --set 选择器 viewDidLoad
这将在您的应用程序中的所有 viewDidLoad 实现上设置断点。 所以选择器是一种方法的全局标识符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.