65 votes

quand utiliser respondsToSelector en objective-c

- (void)someMethod
{
    if ( [delegate respondsToSelector:@selector(operationShouldProceed)] )
    {
        if ( [delegate operationShouldProceed] )
        {
            // do something appropriate
        }
    }
}

El documentation dit :

La précaution n'est nécessaire que pour les méthodes facultatives d'un protocole formel ou les méthodes d'un protocole informel.

Qu'est-ce que cela signifie ? Si j'utilise un protocole formel, je peux juste utiliser [delegate myMethod] ?

84voto

kubi Points 20607

Vous ne l'utilisez pratiquement que lorsque vous pensez en avoir besoin : pour vérifier si un objet implémente la méthode que vous êtes sur le point d'appeler. Habituellement Cela se fait lorsque vous avez des méthodes facultatives ou un protocole informel.

Je n'ai jamais utilisé que respondsToSelector quand j'écris du code qui doit communiquer avec un objet délégué.

if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) {
        [self.delegate engineDidStartRunning:self];
    }

Vous voudrez parfois utiliser respondsToSelector sur toute méthode qui renvoie et id ou générique NSObject lorsque vous n'êtes pas sûr de la classe de l'objet renvoyé.

46voto

Dave DeLong Points 156978

Juste pour ajouter à ce que @kubi a dit, une autre fois que je l'utilise est quand une méthode a été ajoutée à une classe préexistante dans une version plus récente des frameworks, mais j'ai toujours besoin d'être rétrocompatible. Par exemple :

if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) {
  [myObject doAwesomeNewThing];
} else {
  [self doOldWorkaroundHackWithObject:myObject];
}

13voto

Robert Points 10822

Comme l'a mentionné Kubi respondsToSelector est normalement utilisé lorsque vous avez une instance d'une méthode qui se conforme à un protocole.

// Extend from the NSObject protocol so it is safe to call `respondsToSelector` 
@protocol MyProtocol <NSObject> 

// @required by default
- (void) requiredMethod;

@optional

- (void)optionalMethod;

@end

Avec une instance de ce protocole, nous pouvons appeler en toute sécurité n'importe quelle méthode requise.

id <MyProtocol> myObject = ... 
[myObject requiredMethod];

Cependant, les méthodes optionnelles peuvent être implémentées ou non, vous devez donc vérifier au moment de l'exécution.

if ([myObject respondsToSelector:@selector(optionalMethod)]) 
{
     [myObject optionalMethod];
}

Cela permet d'éviter un crash avec un sélecteur non reconnu.


De même, la raison pour laquelle vous devez déclarer les protocoles comme une extension de NSObjects, à savoir

@protocol MyProtocol <NSObject> 

C'est parce que le protocole NSObject déclare l'élément respondsToSelector: sélecteur. Sinon, XCode penserait qu'il n'est pas sûr de l'appeler.

2voto

Wirsing Points 556

Vieille question, mais j'ai appris à être très prudent avec des trucs comme addTarget:@selector(fu :) parce que le nom de la méthode n'est pas vérifié ni inclus dans le refactoring par XCODE. Cela m'a déjà causé pas mal de problèmes. Donc maintenant j'ai pris l'habitude de toujours intégrer des choses comme addTarget ou addObserver dans un respondsToSelector-Check comme ceci :

if([self respondsToSelector:@selector(buttonClicked:)]){
    [self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}else{
    DebugLog(@"Warning - a class or delegate did not respond to selector in class %@", self);
} 

Je sais que ce n'est pas très élégant, mais je préfère ajouter un peu de code passe-partout plutôt que d'avoir un crash inattendu de mes applications dans l'App Store.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X