简体   繁体   English

Objective-C 中的选择器?

[英]Selectors in Objective-C?

First, I'm not sure I really understand what a selector is.首先,我不确定我是否真的理解选择器是什么。 From my understanding, it's the name of a method, and you can assign it to a class of type 'SEL' and then run methods such as respondToSelector to see if the receiver implements that method.根据我的理解,它是一个方法的名称,您可以将它分配给一个类型为“SEL”的类,然后运行诸如 respondToSelector 之类的方法来查看接收方是否实现了该方法。 Can someone offer up a better explanation?有人可以提供更好的解释吗?

Secondly, to this point, I have the following code:其次,到目前为止,我有以下代码:

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]);

However, even though thing is clearly a kind of NSString, and should respond to lowercaseString, I cannot get the 'respondsToSelector' conditional to return "YES"...但是,即使thing显然是一种 NSString,并且应该响应小写字符串,但我无法让 'respondsToSelector' 有条件地返回“YES”......

You have to be very careful about the method names.您必须非常注意方法名称。 In this case, the method name is just " lowercaseString ", not " lowercaseString: " (note the absence of the colon).在这种情况下,方法名称只是“ lowercaseString ”,而不是“ lowercaseString: ”(注意没有冒号)。 That's why you're getting NO returned, because NSString objects respond to the lowercaseString message but not the lowercaseString: message.这就是为什么您NO返回NO的原因,因为NSString对象响应lowercaseString消息而不是lowercaseString:消息。

How do you know when to add a colon?你怎么知道什么时候加冒号? You add a colon to the message name if you would add a colon when calling it, which happens if it takes one argument.如果在调用消息时添加冒号,则在消息名称中添加一个冒号,如果它接受一个参数就会发生这种情况。 If it takes zero arguments (as is the case with lowercaseString ), then there is no colon.如果它接受零个参数(就像lowercaseString的情况),则没有冒号。 If it takes more than one argument, you have to add the extra argument names along with their colons, as in compare:options:range:locale: .如果需要多个参数,则必须添加额外的参数名称及其冒号,如compare:options:range:locale:

You can also look at the documentation and note the presence or absence of a trailing colon.您还可以查看文档并注意尾随冒号的存在与否。

Selectors are an efficient way to reference methods directly in compiled code - the compiler is what actually assigns the value to a SEL. 选择器是直接在编译代码中引用方法的有效方式——编译器实际上是将值分配给 SEL。

Other have already covered the second part of your q, the ':' at the end matches a different signature than what you're looking for (in this case that signature doesn't exist).其他人已经涵盖了您的 q 的第二部分,末尾的 ':' 匹配的签名与您要查找的签名不同(在这种情况下,该签名不存在)。

That's because you want @selector(lowercaseString) , not @selector(lowercaseString:) .那是因为您想要@selector(lowercaseString) ,而不是@selector(lowercaseString:) There's a subtle difference: the second one implies a parameter (note the colon at the end), but - [NSString lowercaseString] does not take a parameter.有一个细微的区别:第二个意味着一个参数(注意末尾的冒号),但是- [NSString lowercaseString]不接受参数。

In this case, the name of the selector is wrong.在这种情况下,选择器的名称是错误的。 The colon here is part of the method signature;这里的冒号是方法签名的一部分; it means that the method takes one argument.这意味着该方法采用一个参数。 I believe that you want我相信你想要

SEL sel = @selector(lowercaseString);

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

Don't think of the colon as part of the function name, think of it as a separator, if you don't have anything to separate (no value to go with the function) then you don't need it.不要将冒号视为函数名称的一部分,而是将其视为分隔符,如果您没有任何要分隔的内容(该函数没有值),那么您就不需要它。

I'm not sure why but all this OO stuff seems to be foreign to Apple developers.我不知道为什么,但所有这些面向对象的东西对 Apple 开发人员来说似乎都是陌生的。 I would strongly suggest grabbing Visual Studio Express and playing around with that too.我强烈建议抓住 Visual Studio Express 并使用它。 Not because one is better than the other, just it's a good way to look at the design issues and ways of thinking.不是因为一个比另一个更好,只是它是一种看待设计问题和思维方式的好方法。

Like

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

It's always good to look at a problem in different ways and programming is the ultimate puzzle.以不同的方式看待问题总是好的,而编程是终极难题。

From my understanding of the Apple documentation, a selector represents the name of the method that you want to call.根据我对 Apple 文档的理解,选择器表示您要调用的方法的名称。 The nice thing about selectors is you can use them in cases where the exact method to be called varies.选择器的好处是您可以在要调用的确切方法发生变化的情况下使用它们。 As a simple example, you can do something like:作为一个简单的例子,您可以执行以下操作:

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

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

A selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled.选择器是用于为对象选择要执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。 A selector by itself doesn't do anything.选择器本身不做任何事情。 It simply identifies a method.它只是标识一个方法。 The only thing that makes the selector method name different from a plain string is that the compiler makes sure that selectors are unique.唯一使选择器方法名称与普通字符串不同的是编译器确保选择器是唯一的。 What makes a selector useful is that (in conjunction with the runtime) it acts like a dynamic function pointer that, for a given name, automatically points to the implementation of a method appropriate for whichever class it's used with.选择器的有用之处在于(结合运行时)它就像一个动态函数指针,对于给定的名称,它自动指向适用于它所使用的任何类的方法的实现。 Suppose you had a selector for the method run, and classes Dog, Athlete, and ComputerSimulation (each of which implemented a method run).假设您有一个用于方法 run 的选择器,以及类 Dog、Athlete 和 ComputerSimulation(每个类都实现了一个方法 run)。 The selector could be used with an instance of each of the classes to invoke its run method—even though the implementation might be different for each.选择器可以与每个类的实例一起使用以调用其 run 方法——即使每个类的实现可能不同。

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

This will set a breakpoint on all viewDidLoad implementations in your app.这将在您的应用程序中的所有 viewDidLoad 实现上设置断点。 So selector is kind of a global identifier for a method.所以选择器是一种方法的全局标识符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM