web-dev-qa-db-fra.com

Appeler dynamiquement une méthode de classe dans Objective C

Supposons que j'ai l'interface Objective C SomeClass qui a une méthode de classe appelée someMethod:

@interface SomeClass : NSObject {
}

+ (id)someMethod;
@end

Dans une autre interface, je veux avoir une méthode d'assistance qui invoquerait dynamiquement someMethod sur une classe comme celle-ci:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

Quelle devrait être l'implémentation de invokeSelector? Est-ce possible du tout?

- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
   // ???
}
41
GregK

Au lieu de:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

appel:

[[SomeClass class] performSelector:@selector(someMethod)];

Exemple (en utilisant GNUstep ...)

fichier A.h

#import <Foundation/Foundation.h>
@interface A : NSObject {}

- (NSString *)description;
+ (NSString *)action;
@end

fichier A.m

#import <Foundation/Foundation.h>
#import "A.h"

@implementation A

- (NSString *)description
{
    return [NSString stringWithString: @"A"];
}

+ (NSString *)action
{
    return [NSString stringWithString:@"A::action"];
}

@end

Ailleurs:

A *a = [[A class] performSelector:@selector(action)];
NSLog(@"%@",a);

Production:

2009-11-22 23:32:41.974 abc[3200] A::action

Belle explication de http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html :

"Dans Objective-C, un objet de classe obtient toutes les méthodes d'instance de la classe racine pour sa hiérarchie. Cela signifie que chaque objet de classe qui descend de NSObject obtient toutes les méthodes d'instance de NSObject - y compris performSelector :."

83
stefanB

Dans Objective-C, les classes sont également des objets. Cependant, les objets de classe sont traités différemment, car ils peuvent appeler les méthodes d'instance de leur classe racine (NSObject ou NSProxy dans Cocoa).

Il est donc possible d'utiliser toutes les méthodes d'instance définies dans NSObject sur les objets de classe et la bonne façon d'invoquer dynamiquement une méthode de classe est:

[aClass performSelector:@selector(aSelector)];

Les Apple docs sont un peu plus spécifiques.

4
Adrian

Vous ne devriez pas implémenter cela vous-même.

Le protocole NSObject a un performSelector: méthode qui fait exactement cela.

2
Ben S

Cette méthode intégrée est-elle ce que vous voulez?

id objc_msgSend(id theReceiver, SEL theSelector, ...)

(Voir les documents de référence d'exécution pour cette fonction.)

2
vanja.