了解Objective-C中选择器的唯一性 [英] Understanding uniqueness of selectors in Objective-C

查看:116
本文介绍了了解Objective-C中选择器的唯一性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在理解选择器"功能的一部分时遇到了问题,如Apple指南中所述.我已经加粗了让我感到困惑的部分:

I am having problem understanding part of the function of "selectors", as described in Apple's guide. I've bolded the parts where I am getting confused:

在Objective-C中,选择器有两个含义.可以用来参考 只是在源代码消息中使用方法的名称时 到一个对象. 尽管如此,它也指的是 编译源代码时替换名称.已编译 选择器的类型为SEL. 所有同名方法都具有 相同的选择器. 对象-这为实施该对象提供了基础 可可中的目标动作设计模式.

In Objective-C, selector has two meanings. It can be used to refer simply to the name of a method when it’s used in a source-code message to an object. It also, though, refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL. All methods with the same name have the same selector. You can use a selector to invoke a method on an object—this provides the basis for the implementation of the target-action design pattern in Cocoa.

方法和选择器为了提高效率,不使用完整的ASCII名称作为 编译代码中的方法选择器.而是由编译器编写每个 方法名称放入表格中,然后将名称与唯一标识符配对 表示运行时的方法. 运行时系统确保 每个标识符都是唯一的:没有两个选择器是相同的,并且所有 具有相同名称的方法具有相同的选择器.

Methods and Selectors For efficiency, full ASCII names are not used as method selectors in compiled code. Instead, the compiler writes each method name into a table, then pairs the name with a unique identifier that represents the method at runtime. The runtime system makes sure each identifier is unique: No two selectors are the same, and all methods with the same name have the same selector.

任何人都可以解释这些位吗?另外,如果不同的类具有相同名称的方法,那么它们也将具有相同的选择器吗?

Can anyone explain these bits? Additionally, if different classes have methods with the same name, will they also have the same selector?

推荐答案

所有选择器都是唯一的-不仅在编译时,而且在运行时通过sel_getUid()或首选的sel_registerName()(主要是首选的sel_registerName()前者由于历史原因仍在附近)– 出于速度 .

All selectors are uniqued -- both at compile time and, dynamically, at runtime through sel_getUid() or the preferred sel_registerName() (the latter being largely preferred, the former still around for historical reasons) -- for speed.

背景故事:要调用方法,运行时需要一个选择器,该选择器标识要调用的内容以及将调用该对象的对象.这就是为什么Objective-C中的每个方法调用都具有两个参数的原因:明显的众所周知的self和不可见的隐式参数_cmd. _cmd是当前正在执行的方法的SEL.也就是说,您可以将此代码粘贴到任何方法中,以查看当前正在执行的方法的名称(选择器):

Back story: to call a method, the runtime needs a selector that identifies what is to be called and an object that it will be called on. This is why every single method call in Objective-C has two parameters: the obvious and well known self and the invisible, implied, parameter _cmd. _cmd is the SEL of the method currently executing. That is, you can paste this code into any method to see the name -- the selector -- of the currently executing method:

NSLog(@"%@", NSStringFromSelector(_cmd));

请注意,_cmd不是 全局变量;它确实是您的方法的一个参数.见下文.

Note that _cmd is not a global; it really is an argument to your method. See below.

通过唯一化选择器,所有基于选择器的操作都使用指针相等性测试来实现,而不是使用字符串处理或完全取消对指针的引用.

By uniquing the selectors, all selector based operations are implemented using pointer equality tests instead of string processing or any pointer de-referencing at all.

尤其是每次您进行方法调用时:

In particular, every single time you make a method call:

[someObject doSomething: toThis withOptions: flags]; // calls SEL doSomething:withOptions:

编译器生成以下代码(或非常紧密相关的变体):

The compiler generates this code (or a very closely related variant):

objc_msgSend(someObject, @selector(doSomething:withOptions:), toThis, flags);

objc_msgSend()要做的第一件事是检查someObject是否为零,如果短路则为(nil-eats-message).接下来(忽略标记的指针)是在someObject的类中查找选择器(实际上是isa指针),找到实现,然后调用它(使用尾部调用优化) ).

The very first thing objc_msgSend() does is check to see if someObject is nil and short-circuit if it is (nil-eats-message). The next (ignoring tagged pointers) is to look up the selector in someObjects class (the isa pointer, in fact), find the implementation, and call it (using a tail call optimization).

查找实现必须快速并且要使其真正快速,您希望找到该方法的实现的关键是尽可能快速和稳定.要做到这一点,您希望密钥可以直接使用并且在整个过程中是全局唯一的.

That find the implementation thing has to be fast and to make it really fast, you want the key to finding the implementation of the method to be as fast and stable as possible. To do that, you want the key to be directly usable and globally unique to the process.

因此,选择器是唯一的.

Thus, the selectors are uniqued.

它还可以节省内存,这是一个了不起的好处,但是如果使Messenger的传输速度提高2倍(但不是2倍提高10倍,甚至是2倍速度提高2倍,Messenger会比今天使用更多的内存).虽然速度至关重要,但是内存的使用也至关重要).

That it also happens to save memory is an fantastic benefit, but the messenger would use more memory than it does today if messenging could be made 2x faster (but not 10x for 2x -- or even 2x memory for 2x speed -- while speed is critical, memory use is also critical, certainly).

如果您真的想深入了解objc_msgSend()的工作原理,我写了

If you really want to dive deep on how objc_msgSend() works, I wrote a bit of a guide. Note that it is slightly out of date as it was written before tagged pointers, blocks-as-implementation, and ARC were disclosed. I should update the articles.

这篇关于了解Objective-C中选择器的唯一性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆