Селекторы в Objective-C?

122

Во-первых, я не уверен, что действительно понимаю, что такое селектор. Насколько я понимаю, это имя метода, и вы можете назначить его классу типа «SEL», а затем запустить такие методы, как responseToSelector, чтобы узнать, реализует ли получатель этот метод. Может кто-нибудь предложить лучшее объяснение?

Во-вторых, на данный момент у меня есть следующий код:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

Однако, хотя thingэто явно разновидность NSString и должна отвечать на lowercaseString, я не могу заставить условие responsedsToSelector вернуть «YES» ...

Craig
источник
Вы хотите прочитать описание селектора на сайте разработчиков Apple: Селекторы .
Lothar
14
Стэнфордский курс CS193P, задание 1B? У меня здесь точно такой же вопрос! :)
Corstian Boerman

Ответы:

181

Вы должны быть очень осторожны с именами методов. В этом случае имя метода просто " lowercaseString", а не " lowercaseString:" (обратите внимание на отсутствие двоеточия). Вот почему вы получаете ответ NO, потому что NSStringобъекты отвечают на lowercaseStringсообщение, но не на lowercaseString:сообщение.

Как узнать, когда нужно добавить двоеточие? Вы добавляете двоеточие к имени сообщения, если добавляете двоеточие при его вызове, что происходит, если он принимает один аргумент. Если он принимает нулевые аргументы (как в случае с lowercaseString), то двоеточие отсутствует. Если требуется более одного аргумента, вы должны добавить имена дополнительных аргументов вместе с их двоеточиями, как в compare:options:range:locale:.

Вы также можете посмотреть документацию и отметить наличие или отсутствие завершающего двоеточия.

Адам Розенфилд
источник
12

Селекторы - это эффективный способ ссылки на методы непосредственно в скомпилированном коде - компилятор - это то, что фактически присваивает значение SEL.

Другой уже охватывал вторую часть вашего q, ':' в конце соответствует другой подписи, отличной от той, которую вы ищете (в этом случае этой подписи не существует).

dstnbrkr
источник
10

Это потому, что вы хотите @selector(lowercaseString), а не @selector(lowercaseString:). Есть небольшая разница: второй подразумевает параметр (обратите внимание на двоеточие в конце), но - [NSString lowercaseString]не принимает параметр.

mipadi
источник
5

В этом случае имя селектора неверно. Двоеточие здесь является частью сигнатуры метода; это означает, что метод принимает один аргумент. Я верю что ты хочешь

SEL sel = @selector(lowercaseString);
MKB
источник
3

Метод NSString - lowercaseString(0 аргументов), а не lowercaseString:(1 аргумент).

Николас Райли
источник
1

Не думайте о двоеточии как о части имени функции, считайте его разделителем, если вам нечего отделять (нет значения для функции), тогда оно вам не нужно.

Я не уверен, почему, но весь этот объектно-ориентированный материал кажется чуждым разработчикам Apple. Я настоятельно рекомендую взять Visual Studio Express и поиграть с этим тоже. Не потому, что один лучше другого, просто это хороший способ взглянуть на проблемы дизайна и способы мышления.

подобно

introspection = reflection
+ before functions/properties = static
- = instance level

Всегда хорошо смотреть на проблему по-разному, а программирование - это главная головоломка.


источник
0

Насколько я понимаю в документации Apple, селектор представляет имя метода, который вы хотите вызвать. Селекторы хороши тем, что их можно использовать в тех случаях, когда конкретный вызываемый метод варьируется. В качестве простого примера вы можете сделать что-то вроде:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
moonman239
источник
0

Согласно документации Apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Селектор - это имя, используемое для выбора метода, выполняемого для объекта, или уникальный идентификатор, заменяющий имя при компиляции исходного кода. Селектор сам по себе ничего не делает. Он просто определяет метод. Единственное, что отличает имя метода селектора от простой строки, - это то, что компилятор обеспечивает уникальность селекторов. Что делает селектор полезным, так это то, что (в сочетании со средой выполнения) он действует как динамический указатель на функцию, который для данного имени автоматически указывает на реализацию метода, подходящего для любого класса, с которым он используется. Предположим, у вас есть селектор для запуска метода и классы Dog, Athlete и ComputerSimulation (каждый из которых реализует запуск метода).

Пример: (lldb) breakpoint --set selector viewDidLoad

Это установит точку останова для всех реализаций viewDidLoad в вашем приложении. Так что селектор - это своего рода глобальный идентификатор метода.

Адриан
источник