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 ?

4

3 回答 3

4

选择器是“内部”(唯一)字符串。运行时维护一个内部字符串(选择器)池。如果要实习字符串,可以使用 C 字符串调用运行时函数sel_getUid()sel_registerName()运行时函数,它会返回类型不透明的句柄SEL(选择器)。如果该字符串之前已被实习过,则此选择器保证与前一个相同。相反,从选择器中,您可以使用sel_getName(). 在 Cocoa 中,您将使用NSSelectorFromString()and NSStringFromSelector(),它对NSString对象进行操作,而不是使用上述低级运行时函数。

大多数时候,您不会在程序中间进行字符串和选择器之间的转换。相反,选择器在编译时已经被硬编码。当你执行一个方法调用 like[foo something: bar]时,它​​会被编译成类似的东西objc_msgSend(foo, @selector(something:), bar),选择器字面量 like@selector(something:)将被编译成对编译器生成的二进制选择器表的引用,类似于全局变量。当一个模块被链接时,它的选择器表与主程序的选择器表合并,以保证选择器的唯一性。

于 2015-04-09T19:55:51.697 回答
4

同样的问题也困扰了我一段时间。所以我研究了运行时实现。这就是我发现的:

所有的选择器都存储在一个哈希集中。如果您已经注册了选择器,它将由 objc 运行时使用 c 函数 sel_getUid 和 sel_registerName 返回,如果未注册,它将由相同的函数创建。它们都具有相同的实现和行为,因为它们正在调用名为 __sel_registerName 的私有函数。旧运行时使用指向 struct __objc_sel_set 的指针来存储值。

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 */
};

新的运行时使用指向 struct NXMapTable 的指针:

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

希望这可以帮助。

于 2015-09-03T03:05:28.830 回答
2

看一下Apples解释

选择器是用于选择要为对象执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。选择器本身不做任何事情。它只是标识一种方法。使选择器方法名称与纯字符串不同的唯一原因是编译器确保选择器是唯一的。使选择器有用的是(与运行时一起)它就像一个动态函数指针,对于给定的名称,它会自动指向适用于与它一起使用的任何类的方法的实现。假设您有一个用于方法 run 的选择器,以及 Dog、Athlete 和 ComputerSimulation 类(每个都实现了一个方法 run)。

methods如果您看一下@AntoniKedracki 帖子,就会有关于and的非常好的解释selectors

只是帖子的简短摘要:

每个objective-c方法都将在astruct中表示c。该结构如下所示:

struct objc_method {
    SEL method_name                                          
    char *method_types                                       
    IMP method_imp                                           
} 

因此选择器将由C方法名称自动创建并保存在SEL method_name. 如果您想访问objc_method您应该包含 , <objc/runtime.h>,那么您将能够使用运行时方法。

有关更多信息,请查看另一篇文章中的链接。

于 2015-04-09T08:48:13.003 回答