Селекторы в Цели С

Во-первых, я не уверен, что действительно понимаю, что такое селектор. Насколько я понимаю, это имя метода, и вы можете назначить его классу типа "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" для возврата "ДА"...

8 ответов

Решение

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

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

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

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

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

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

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

SEL sel = @selector(lowercaseString);

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

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

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

подобно

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

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

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

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];

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

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

Пример: (lldb) точка останова - set селектор viewDidLoad

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

Другие вопросы по тегам