18 votes

Accéder à une méthode dans une super-classe alors qu'elle n'est pas exposée

Dans une sous-classe, je surcharge une méthode qui n'est pas exposée dans la super-classe. Je sais que j'ai la bonne signature puisqu'elle surcharge avec succès l'implémentation de la superclasse. Cependant, dans le cadre de la nouvelle implémentation, je dois appeler l'implémentation de la superclasse à partir de l'implémentation de la sous-classe.

Parce qu'elle n'est pas exposée, je dois invoquer la méthode par le biais d'un appel à performSelector :

SEL superClassSelector = NSSelectorFromString(@"methodToInvoke");
[super performSelector:superClassSelector];

Cependant, dans mon application, cela se traduit par une boucle récursive infinie dans laquelle l'implémentation de la sous-classe est invoquée chaque fois que j'essaie d'invoquer l'implémentation de la superclasse.

Qu'en pensez-vous ?

Je suis conscient qu'il s'agit d'une situation atypique, mais il n'y a malheureusement aucun moyen de contourner ce que j'essaie de faire.

45voto

ModernCarpentry Points 597

La façon dont j'ai traité ce problème est de redéclarer l'interface de votre super-classe dans le fichier d'implémentation de votre sous-classe avec la méthode que vous voulez appeler à partir de la sous-classe.

@interface MySuperclass()
- (void)superMethodIWantToCall;
@end

@implementation MySubclass

- (void)whateverFunction  {
    //now call super method here
    [super superMethodIWantToCall];
}

@end

Je ne sais pas si c'est la meilleure façon de procéder, mais c'est simple et ça marche pour moi !

9voto

Josh Caswell Points 40397

Cela ne fonctionne pas car vous n'envoyez que des performSelector: et non le sélecteur que vous lui passez, à la superclasse. performSelector: recherche toujours la méthode dans la liste des méthodes de la classe actuelle. Vous obtenez ainsi la même implémentation de sous-classe.

La manière la plus simple d'y parvenir est d'écrire votre propre appel à la fonction objc_msgSendSuper() :

// Top level (this struct isn't exposed in the runtime header for some reason)
struct objc_super
{
    id __unsafe_unretained reciever;
    Class __unsafe_unretained superklass;
};

// In the subclass's method
struct objc_super sup = {self, [self superclass]};
objc_msgSendSuper(&sup, _cmd, other, args, go, here);

Cela peut poser des problèmes dans le cas général, comme l'a souligné Rob Napier ci-dessous. J'ai suggéré cela sur la base de l'hypothèse

2voto

Ismael Points 3030

Une solution consiste à créer une catégorie de votre classe dans un fichier séparé avec la méthode que vous essayez d'exposer

@interface MyClass (ProtectedMethods)

- (void)myMethod;

@end

et sur le site .m

@implementation MyClass (ProtectedMethods)

- (void)myMethod {

}

@end

Importez ensuite cette catégorie à partir de vos fichiers .m, et le tour est joué. Ce n'est pas très joli, mais ça fera l'affaire.

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