Sélecteurs en Objective-C?

122

Premièrement, je ne suis pas sûr de bien comprendre ce qu'est un sélecteur. D'après ce que je comprends, c'est le nom d'une méthode, et vous pouvez l'assigner à une classe de type 'SEL', puis exécuter des méthodes telles que respondToSelector pour voir si le récepteur implémente cette méthode. Quelqu'un peut-il offrir une meilleure explication?

Deuxièmement, à ce stade, j'ai le code suivant:

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]);

Cependant, même si thingc'est clairement une sorte de NSString, et que je devrais répondre à lowercaseString, je ne peux pas obtenir le conditionnel 'respondsToSelector' pour retourner "YES" ...

Craig
la source
Vous voulez lire la description du sélecteur sur le site des développeurs Apple: Sélecteurs .
lothar
14
Cours de Stanford CS193P affectation 1B? J'ai exactement la même question ici! :)
Corstian Boerman

Réponses:

181

Vous devez faire très attention aux noms des méthodes. Dans ce cas, le nom de la méthode est simplement " lowercaseString", pas " lowercaseString:" (notez l'absence de deux points). C'est pourquoi vous êtes NOrenvoyé, car les NSStringobjets répondent au lowercaseStringmessage mais pas au lowercaseString:message.

Comment savoir quand ajouter un deux-points? Vous ajoutez un signe deux-points au nom du message si vous ajoutez un deux-points lors de son appel, ce qui se produit s'il prend un argument. S'il ne prend aucun argument (comme c'est le cas avec lowercaseString), alors il n'y a pas de deux-points. Si cela prend plus d'un argument, vous devez ajouter les noms d'arguments supplémentaires avec leurs deux-points, comme dans compare:options:range:locale:.

Vous pouvez également consulter la documentation et noter la présence ou l'absence d'un deux-points de fin.

Adam Rosenfield
la source
12

Les sélecteurs sont un moyen efficace de référencer des méthodes directement dans le code compilé - le compilateur est ce qui affecte réellement la valeur à un SEL.

D'autres ont déjà couvert la deuxième partie de votre q, le «:» à la fin correspond à une signature différente de celle que vous recherchez (dans ce cas, cette signature n'existe pas).

dstnbrkr
la source
10

C'est parce que tu veux @selector(lowercaseString), non @selector(lowercaseString:). Il y a une différence subtile: la seconde implique un paramètre (notez les deux points à la fin), mais - [NSString lowercaseString]ne prend pas de paramètre.

mipadi
la source
5

Dans ce cas, le nom du sélecteur est erroné. Le deux-points ici fait partie de la signature de la méthode; cela signifie que la méthode prend un argument. Je crois que tu veux

SEL sel = @selector(lowercaseString);
mkb
la source
3

La méthode de NSString est lowercaseString(0 argument), pas lowercaseString:(1 argument).

Nicholas Riley
la source
1

Ne considérez pas les deux points comme faisant partie du nom de la fonction, pensez-y comme un séparateur, si vous n'avez rien à séparer (aucune valeur pour aller avec la fonction), vous n'en avez pas besoin.

Je ne sais pas pourquoi, mais tout ce truc OO semble être étranger aux développeurs Apple. Je suggérerais fortement de saisir Visual Studio Express et de jouer avec cela aussi. Non pas parce que l'un est meilleur que l'autre, mais c'est un bon moyen d'examiner les problèmes de conception et les modes de pensée.

Comme

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

Il est toujours bon de regarder un problème de différentes manières et la programmation est le casse-tête ultime.


la source
0

D'après ma compréhension de la documentation Apple, un sélecteur représente le nom de la méthode que vous souhaitez appeler. La bonne chose à propos des sélecteurs est que vous pouvez les utiliser dans les cas où la méthode exacte à appeler varie. À titre d'exemple simple, vous pouvez faire quelque chose comme:

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

Selon les documents Apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Un sélecteur est le nom utilisé pour sélectionner une méthode à exécuter pour un objet, ou l'identificateur unique qui remplace le nom lorsque le code source est compilé. Un sélecteur en lui-même ne fait rien. Il identifie simplement une méthode. La seule chose qui rend le nom de la méthode de sélection différent d'une chaîne simple est que le compilateur s'assure que les sélecteurs sont uniques. Ce qui rend un sélecteur utile, c'est que (en conjonction avec le runtime) il agit comme un pointeur de fonction dynamique qui, pour un nom donné, pointe automatiquement vers l'implémentation d'une méthode appropriée pour la classe avec laquelle il est utilisé. Supposons que vous disposiez d'un sélecteur pour l'exécution de la méthode et des classes Dog, Athlete et ComputerSimulation (chacune implémentant une méthode run).

Exemple: (lldb) breakpoint --set selector viewDidLoad

Cela définira un point d'arrêt sur toutes les implémentations de viewDidLoad dans votre application. Le sélecteur est donc une sorte d'identifiant global pour une méthode.

Adrian
la source