3

I don't quite get the Objective-C selectors. The problem is: Where are Objective-C selectors stored ?

How do Objective-C Compiler and Runtime System work, so that they convert the method names into SEL ?

denis631
  • 1,765
  • 3
  • 17
  • 38

3 Answers3

4

Selectors are "interned" (uniquified) strings. The runtime maintains a pool of interned strings (selectors). If you want to intern a string, you call either the sel_getUid() or the sel_registerName() runtime function with a C string, and it returns an opaque handle of type SEL (the selector). If the string has already been interned before, this selector is guaranteed to be equal to the previous one. Conversely, from a selector you can get the string back using sel_getName(). In Cocoa you would use NSSelectorFromString() and NSStringFromSelector(), which operate on NSString objects, instead of using the above low-level runtime functions.

Most of the time, you will not be doing conversion between strings and selectors in the middle of your program. Instead, the selector will have already been hard-coded at compile-time. When you do a method call like [foo something: bar], it is compiled down into something like objc_msgSend(foo, @selector(something:), bar), and the selector literal like @selector(something:) will be compiled into a reference into the binary's selector table generated by the compiler, similar to with global variables. When a module is linked, its selector table is merged with the main program's selector table to guarantee the uniqueness of selectors.

newacct
  • 119,665
  • 29
  • 163
  • 224
4

The same question was bothering me too for a while. So I've looked into the runtime implementation. That's what I've found:

All the selectors are stored in a hash set. If you already have a registered selector, it will be returned by the objc runtime using c functions sel_getUid & sel_registerName, if not registered, it will be created by the same functions. Both of them have the same implementation & behavior, 'cause they are calling private function named __sel_registerName. Old runtime uses pointer to struct __objc_sel_set to store values.

struct __objc_sel_set {
uint32_t _count;            /* number of slots used */
uint32_t _capacity;         /* maximum number of used slots */
uint32_t _bucketsNum;       /* number of slots */
SEL *_buckets;              /* can be NULL if not allocated yet */
};

New runtime uses pointer to struct NXMapTable:

typedef struct _NXMapTable {
/* private data structure; may change */
const struct _NXMapTablePrototype   *prototype;
unsigned    count;
unsigned    nbBucketsMinusOne;
void    *buckets;
} NXMapTable OBJC_MAP_AVAILABILITY;

Hope this helps.

PAcan
  • 871
  • 2
  • 15
  • 32
  • I have little knowledge about the runtime system and how it works. Are the selectors stored in a hashSet, which is created by the runtime ? And why the buckets are void* in the new runtime, but not the SEL* ? – denis631 Sep 03 '15 at 07:11
2

Have a look at Apples explanation:

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

If you have a look at @AntoniKedracki post there is a really good explanation about methods and selectors.

Just a short summary from the post:

Every objective-c method will be represented inside a struct in c. The struct looks like this:

struct objc_method {
    SEL method_name                                          
    char *method_types                                       
    IMP method_imp                                           
} 

So the selector will be created by C automatically from the method name and saved inside the SEL method_name. If you want to get access to the objc_method you should include the <objc/runtime.h>, than you will be able to use the runtime methods.

For more information have a look at the link in the other post.

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
  • 1
    What do you mean internally ? As I understood it doesn't point to anything, it is just a global key, which is used in order to find the IMP's for the specific class. So before objc_msgSend is sent, sel_registerName(...) is called in order to identify the selector ? – denis631 Apr 09 '15 at 08:55
  • I wanted to say, there is no object you can call to get a list of `selectors` which have been created. Your question looked like you were looking for a place where you can access them all – Alex Cio Apr 09 '15 at 09:05
  • 2
    The problem is not accessing all of them, but understanding where they are stored. Since if sel_registerName(...) is searching for a selector, it should be looking somewhere, right ? – denis631 Apr 09 '15 at 10:34