[英]Where are Objective-C selectors registered/stored?
我不太了解Objective-C选择器。 问题是:Objective-C选择器存储在哪里?
Objective-C编译器和运行时系统如何工作,以便将方法名称转换为SEL?
选择器是“实习”(未加工)的字符串。 运行时维护一个实习字符串池(选择器)。 如果要实习字符串,则使用C字符串调用sel_getUid()
或sel_registerName()
运行时函数,并返回SEL
类型的不透明句柄(选择器)。 如果字符串之前已经被中断,则此选择器保证等于前一个。 相反,从选择器中,您可以使用sel_getName()
获取字符串。 在Cocoa中,您将使用NSSelectorFromString()
和NSStringFromSelector()
,它们对NSString
对象进行操作,而不是使用上述低级运行时函数。
大多数情况下,您不会在程序中间进行字符串和选择器之间的转换。 相反,选择器在编译时已经被硬编码了。 当你执行像[foo something: bar]
这样的方法调用时,它被编译成类似objc_msgSend(foo, @selector(something:), bar)
,而像@selector(something:)
这样的选择器文字将被编译成对编译器生成的二进制选择器表的引用,类似于全局变量。 链接模块时,其选择器表与主程序的选择器表合并,以保证选择器的唯一性。
同样的问题也困扰了我一段时间。 所以我研究了运行时实现。 这就是我发现的:
所有选择器都存储在哈希集中。 如果您已经有一个已注册的选择器,它将由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;
希望这可以帮助。
看看Apples
解释 :
选择器是用于选择要为对象执行的方法的名称,或者是在编译源代码时替换名称的唯一标识符。 选择器本身不做任何事情。 它只是识别一种方法。 使选择器方法名称与普通字符串不同的唯一因素是编译器确保选择器是唯一的。 使选择器有用的原因是(与运行时一起)它就像一个动态函数指针,对于给定的名称,它自动指向适用于它所使用的任何类的方法的实现。 假设你有一个方法运行的选择器,以及类Dog,Athlete和ComputerSimulation(每个都实现了一个方法运行)。 选择器可以与每个类的实例一起使用以调用其run方法 - 即使每个类的实现可能不同。
如果你看一下@AntoniKedracki的帖子,对methods
和selectors
有一个非常好的解释。
只是帖子的简短摘要:
每个objective-c方法都将在c
的struct
中表示。 结构看起来像这样:
struct objc_method {
SEL method_name
char *method_types
IMP method_imp
}
因此,选择器将由C
自动从方法名称创建并保存在SEL method_name
。 如果要访问objc_method
,则应该包含<objc/runtime.h>
,而不是可以使用运行时方法。
有关更多信息,请查看其他帖子中的链接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.