web-dev-qa-db-fra.com

Comment se débarrasser de l'avertissement de «sélecteur non déclaré»

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

160
epologee

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
247
Klaas

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.

191
sergio

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]];
}
52
Jacob Relkin

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
7
Quixiote

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.

7
Mark Patterson

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

5
i_mush

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 ...

3
Aviel Gross

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.

2
Repose

Vous pouvez le désactiver dans Xcode comme dans la capture d'écran:

enter image description here

2
SmallChess

Vous pouvez également convertir l'objet en question en un identifiant afin d'éviter l'avertissement:

if ([object respondsToSelector:@selector(myMethod)]) {
    [(id)object myMethod];
}
1
Swindler

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.

0
Louis St-Amour