Je veux utiliser un sélecteur sur une instance de NSObject sans la nécessité d'un protocole implémenté. Par exemple, une méthode de catégorie doit définir une propriété error si l'instance NSObject à laquelle elle est appelée la prend en charge. C'est le code, et le code fonctionne comme prévu:
if ([self respondsToSelector:@selector(setError:)])
{
[self performSelector:@selector(setError:) withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}
Cependant, le compilateur ne voit aucune méthode autour avec la signature setError: il me donne donc un avertissement pour chaque ligne contenant l'extrait @selector(setError:)
:
Undeclared selector 'setError:'
Je ne veux pas avoir à déclarer un protocole pour se débarrasser de cet avertissement, car je ne veux pas que toutes les classes qui l'utilisent puissent implémenter quoi que ce soit de spécial. Juste par convention, je veux qu’ils aient un setError:
méthode ou propriété.
Est-ce faisable? Comment?
À votre santé,
EP
Une autre option serait de désactiver l'avertissement avec:
#pragma GCC diagnostic ignored "-Wundeclared-selector"
Vous pouvez placer cette ligne dans le fichier .m où l'avertissement se produit.
Mise à jour:
Cela fonctionne aussi avec LLVM comme ceci:
#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Wundeclared-selector"
... your code here ...
#pragma clang diagnostic pop
Regardez NSSelectorFromString .
SEL selector = NSSelectorFromString(@"setError:");
if ([self respondsToSelector:selector])
Cela vous permettra de créer un sélecteur au moment de l'exécution, au lieu de le faire lors de la compilation via le @selector
mot-clé, et le compilateur n'aura aucune chance de se plaindre.
Je pense que c'est parce que, pour une raison quelconque, le sélecteur n'est pas enregistré avec le moteur d'exécution.
Essayez d’enregistrer le sélecteur via sel_registerName()
:
SEL setErrorSelector = sel_registerName("setError:");
if([self respondsToSelector:setErrorSelector]) {
[self performSelector:setErrorSelector withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}
Je me rends compte que je suis un peu en retard par rapport à ce fil de discussion, mais pour être complet, vous pouvez désactiver globalement cet avertissement à l'aide des paramètres de construction cibles.
Dans la section "Avertissements Apple LLVM - Objective-C", modifiez:
Undeclared Selector - NO
J'ai eu ce message pour partir en incluant le fichier avec la méthode. Rien d'autre n'a été utilisé dans ce fichier.
Si votre classe implémente la méthode setError: (même en déclarant dynamic le séparateur de la propriété d'erreur éventuelle), vous voudrez peut-être la déclarer dans votre fichier d'interface (.h), ou si vous n'aimez pas le montrer ainsi, vous pourriez essayez avec le tour compliqué PrivateMethods:
@interface Yourclass (PrivateMethods)
- (void) yourMethod1;
- (void) yourMethod2;
@end
juste avant votre @implementation, cela devrait cacher les avertissements;).
Une macro vraiment confortable à mettre dans votre .pch
ou Common.h
ou où vous voulez:
#define SUPPRESS_UNDECLARED_SELECTOR_LEAK_WARNING(code) \
_Pragma("clang diagnostic Push") \
_Pragma("clang diagnostic ignored \"-Wundeclared-selector"\"") \
code; \
_Pragma("clang diagnostic pop") \
C'est une édition de cette question pour un problème similaire ...
Une autre façon d'éviter cet avertissement est de vous assurer que votre méthode de sélecteur ressemble à ceci:
-(void) myMethod :(id) sender{
}
N'oubliez pas "expéditeur (id)" si vous souhaitez accepter n'importe quel expéditeur ou spécifier un type d'objet émetteur si vous préférez.
Vous pouvez également convertir l'objet en question en un identifiant afin d'éviter l'avertissement:
if ([object respondsToSelector:@selector(myMethod)]) {
[(id)object myMethod];
}
Alors que la bonne réponse consiste probablement à informer Xcode via des importations ou à enregistrer le sélecteur qu'un tel sélecteur existe, dans mon cas, il me manquait un point-virgule. Avant de "corriger" l'erreur, assurez-vous que l'erreur est peut-être correcte et que votre code ne l'est pas. J'ai trouvé l'erreur dans l'exemple MVCNetworking d'Apple, par exemple.