Подтвердить что ты не робот

Почему мы не можем использовать C-строки как SELs?

Итак, я снова возился с objc-runtime (неожиданным сюрпризом), и я нашел интересный блок кода здесь:

const char *sel_getName(SEL sel) {
#if SUPPORT_IGNORED_SELECTOR_CONSTANT
    if ((uintptr_t)sel == kIgnore) return "<ignored selector>";
#endif
    return sel ? (const char *)sel : "<null selector>";
}

Итак, это говорит мне, что a SEL эквивалентен C-строке, в каждом манере. Выполнение шестнадцатеричного дампа первых 16 байтов SEL, содержащего @selector(addObject:), дает следующее:

61 64 64 4F 62 6A 65 63 74 3A 00 00 00 00 00

Что равно C-строке addObject:.

Сказав это, почему этот код сбой, когда я использую C-строку в качестве селектора?

SEL normalSEL  = @selector(addObject:);
SEL cStringSEL = (SEL) "addObject:";

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", nil];

[arr performSelector:normalSEL withObject:@"3"];
[arr performSelector:cStringSEL withObject:@"4"];

NSLog(@"%@", arr);

Насколько я могу судить, содержимое селекторов одинаково, поэтому почему во второй аварийный сигнал со следующим сообщением об ошибке?

*** Завершение приложения из-за неотображенного исключения "NSInvalidArgumentException",     reason: '- [__ NSArrayM addObject:]: непризнанный селектор, отправленный в экземпляр     0x101918720 '***

4b9b3361

Ответ 1

Селекторы интернированы C строк и сравниваются по их адресу, а не по содержанию. Содержимое строки используется только для преобразования в/из внешнего строкового представления. Для повышения производительности выполняется интернирование - когда среда выполнения ищет реализацию метода, которая соответствует селектору, он может сравнивать указатели селектора напрямую, а не разыгрывать каждый указатель и сравнивать символы.