Premièrement, je ne suis pas sûr de bien comprendre ce qu'est un sélecteur. D'après ce que j'ai compris, il s'agit du nom d'une méthode. Vous pouvez l'affecter à une classe de type 'SEL', puis exécuter des méthodes telles que respondToSelector pour voir si le destinataire 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 thing
est clairement une sorte de NSString et doit répondre à lowercaseString, je ne peux pas conditionner le paramètre 'respondsToSelector' pour retourner "OUI" ...
Vous devez faire très attention aux noms de méthodes. Dans ce cas, le nom de la méthode est simplement "lowercaseString
" et non pas "lowercaseString:
" (notez l'absence de deux points). C'est pourquoi vous obtenez NO
renvoyé, car les objets NSString
répondent au message lowercaseString
mais pas au message lowercaseString:
.
Comment savez-vous quand ajouter un colon? Vous ajoutez deux points au nom du message si vous voulez en ajouter, ce qui se produit s'il ne faut qu'un seul argument. S'il ne prend aucun argument (comme c'est le cas avec lowercaseString
), alors il n'y a pas de deux points. S'il faut plus d'un argument, vous devez ajouter les noms d'arguments supplémentaires ainsi que leurs deux points, comme dans compare:options:range:locale:
.
Vous pouvez également consulter la documentation et noter la présence ou non de deux points.
C'est parce que vous voulez @selector(lowercaseString)
, pas @selector(lowercaseString:)
. Il existe une différence subtile: le second implique un paramètre (notez les deux points à la fin), mais - [NSString lowercaseString]
ne prend pas de paramètre.
Les sélecteurs sont un moyen efficace de référencer des méthodes directement dans le code compilé - le compilateur est ce qui attribue la valeur à un SEL.
Les autres ont déjà couvert la deuxième partie de votre q, le ':' à la fin correspond à une signature différente de celle recherchée (dans ce cas, cette signature n'existe pas).
Dans ce cas, le nom du sélecteur est incorrect. Les deux points font ici 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);
La méthode de NSString est lowercaseString
(0 arguments), pas lowercaseString:
(1 argument).
Ne considérez pas les deux points comme faisant partie du nom de la fonction, mais plutôt comme un séparateur. Si vous n'avez rien à séparer (aucune valeur associée à la fonction), vous n'en avez pas besoin.
Je ne sais pas pourquoi, mais tout cela 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, 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 d'examiner un problème de différentes manières et la programmation est le casse-tête ultime.
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 différencie le nom de la méthode de sélecteur d'une chaîne en clair est que le compilateur s'assure que les sélecteurs sont uniques. Ce qui rend un sélecteur utile, c’est qu’il (en conjonction avec le moteur d’exécution) agisse comme un pointeur de fonction dynamique qui, pour un nom donné, pointe automatiquement vers l’implémentation d’une méthode appropriée à la classe avec laquelle il est utilisé. Supposons que vous disposiez d'un sélecteur pour l'exécution de la méthode et que vous ayez les classes Dog, Athlete et ComputerSimulation (chacune d'entre elles implémentant une exécution de méthode). Le sélecteur peut être utilisé avec une instance de chacune des classes pour appeler sa méthode d'exécution, même si l'implémentation peut être différente pour chacune.
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'identificateur global pour une méthode.
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. Comme exemple simple, vous pouvez faire quelque chose comme:
SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];