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:

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.

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?

4 Answers
4

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.

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

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.

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.

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).

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.

Look at the SEL type, you don't have to define which class this selector is from, you just give it a method name, for example:

SEL animationSelector = @selector(addAnimation:forKey:);

You can imagine it as a streetname, for example. Many cities can have the same streetnames, but a streetname without a city is worthless. Same for selectors, you can define a selector without adding the object where it's in. But it's complete worthless without fitting class..

A selector is the same for all methods that have the same name and parameters — regardless of which objects define them, whether those objects are related in the class hierarchy, or actually have nothing to do with each other. At runtime, Objective-C goes to the class and outright asks it, "Do you respond to this selector?", and calls the resulting function pointer if it does.

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.

In a screwed up way, this makes sense. If Method A and Method B have the exact same name and arguments, wouldn't it be more efficient to store their selector as one lookup and query the receiver instead of deciding between two basically equally named selectors at runtime?

I can give an example from the source code objc-sel.mm, but when you use sel_registerUid() (used behind the scenes in @selector()),
It copies the input string into an internal buffer (if the string hasn't been registered before), for which all future SELs point to.

While the details are correct, the conclusion misses the most important reasons why this is done.
–
bbumJun 15 '12 at 14:18

2

Not a clarity issue, but accuracy. It is for speed, speed, speed. Check out the cache lookup implementation for objc_msgSend(); every single method call -- all 100s of millions of them when you boot a device -- relies on the uniqueness of selectors to allow the cache lookup and message dispatch to be as fast as possible (or as fast as the team knows how to make it, anyway :).
–
bbumJun 15 '12 at 14:38