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

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

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

SEL sel = @selector(lowercaseString);

Ответ 5

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

Ответ 6

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

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

Как

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

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

Ответ 7

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

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

Ответ 8

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

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

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

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