Где зарегистрированы / хранятся селекторы Objective-C?
Я не совсем понимаю селекторы Objective-C. Проблема в том, где хранятся селекторы Objective-C?
Как работают Objective-C Compiler и Runtime System, чтобы они преобразовывали имена методов в SEL?
3 ответа
Селекторы являются "интернированными" (неунифицированными) строками. Среда выполнения поддерживает пул интернированных строк (селекторов). Если вы хотите интернировать строку, вы вызываете либо sel_getUid()
или sel_registerName()
функция времени выполнения со строкой C, и она возвращает непрозрачный дескриптор типа SEL
(селектор). Если строка уже была интернирована ранее, этот селектор гарантированно будет равен предыдущему. И наоборот, из селектора вы можете получить строку обратно, используя sel_getName()
, В какао вы бы использовали NSSelectorFromString()
а также NSStringFromSelector()
, которые работают на NSString
объекты, вместо использования вышеупомянутых низкоуровневых функций времени выполнения.
В большинстве случаев вы не будете выполнять преобразование между строками и селекторами в середине вашей программы. Вместо этого селектор уже будет жестко запрограммирован во время компиляции. Когда вы делаете вызов метода, как [foo something: bar]
, это скомпилировано в нечто вроде objc_msgSend(foo, @selector(something:), bar)
и селектор буквальный вроде @selector(something:)
будет скомпилирован в ссылку на таблицу выбора двоичного файла, сгенерированную компилятором, аналогично глобальным переменным. Когда модуль связан, его таблица селекторов объединяется с таблицей селекторов основной программы, чтобы гарантировать уникальность селекторов.
Этот же вопрос меня тоже некоторое время беспокоил. Итак, я посмотрел на реализацию во время выполнения. Вот что я нашел:
Все селекторы хранятся в хэш-наборе. Если у вас уже есть зарегистрированный селектор, он будет возвращен средой выполнения objc с использованием функций c sel_getUid & sel_registerName; если он не зарегистрирован, он будет создан теми же функциями. Оба они имеют одинаковую реализацию и поведение, потому что они вызывают приватную функцию с именем __sel_registerName. Старая среда выполнения использует указатель на структуру __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 */
};
Новая среда выполнения использует указатель на структуру 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). Селектор может использоваться с экземпляром каждого из классов для вызова его метода run - даже если реализация для каждого из них может быть разной.
Если вы посмотрите на пост @AntoniKedracki, есть действительно хорошее объяснение methods
а также selectors
,
Просто краткое резюме из поста:
Каждый метод target-c будет представлен внутри struct
в c
, Структура выглядит так:
struct objc_method {
SEL method_name
char *method_types
IMP method_imp
}
Таким образом, селектор будет создан C
автоматически из имени метода и сохраняется внутри SEL method_name
, Если вы хотите получить доступ к objc_method
Вы должны включить <objc/runtime.h>
, чем вы сможете использовать методы времени выполнения.
Для получения дополнительной информации посмотрите ссылку в другом посте.