Je veux juste obtenir un nom de sélecteur, et les arguments, l'expéditeur, ou une instance NSInvocation à chaque fois que j'envoie un message à un objet. Est-ce possible ? Quelque chose comme forwardInvocation :, mais dans chaque cas (chaque appel de méthode).
Réponses
Trop de publicités?Il existe un moyen d'obtenir le nom du sélecteur et la cible en utilisant les paramètres cachés dans la messagerie objective-c. À partir de La documentation d'Apple :
Lorsque objc_msgSend trouve la procédure qui implémente une méthode, il appelle la procédure et lui transmet tous les arguments du message. Il passe également à la procédure deux arguments cachés :
L'objet récepteur Le sélecteur de la méthode
Ainsi, dans une méthode, vous pouvez obtenir ce qui suit :
id target = getTheReceiver();
SEL method = getTheMethod();
Si cela ne suffit toujours pas à répondre à vos besoins, vous pouvez procéder comme suit :
- Créez une classe appelée
Helper
. - Ajoutez une référence à la classe à partir de laquelle vous allez appeler les méthodes, dans ce format :
id <HelperDelegate> myClassReference;
- Lorsque vous devez faire un
[self method]
créez plutôt une instance de cetteHelper
et appeler la méthode sur elle comme[helper method];
et ajoutez ceci[helper setMyClassReference:self];
. - L'application devrait se planter, mais ensuite, il suffit d'ajouter l'élément
forwardInvocation:
sur leHelper
classe. A partir de là, vous pourrez obtenir laNSInvocation
objet. Fais ce que tu dois faire, et ensuite :[anInvocation invokeWithTarget:myClassReference];
afin que vous puissiez transmettre le message à l'appelant original.
P.S : Même si cela ne répond pas à votre question, +1 pour la question Ça m'a vraiment fait réfléchir.
J'ai donc créé cette classe, qui fonctionne comme un charme.
.h
@protocol PGMessageObserverDelegate
-(void)observedInvocation:(NSInvocation*) invocation willSendToObject:(id) object;
-(void)observedInvocation:(NSInvocation*) invocation didSendToObject:(id) object;
@end
@interface PGMessageObserver : NSObject
@property (nonatomic, readonly) id observable;
@property (nonatomic, readonly) id <PGMessageObserverDelegate> delegate;
+(id)messageObserverObserving:(id) observable delegate:(id) delegate;
@end
.m
#import "PGMessageObserver.h"
@interface PGMessageObserver ()
-(id)initWithObservable:(id) observable delegate:(id) delegate;
@end
@implementation PGMessageObserver
@synthesize observable = _observable;
@synthesize delegate = _delegate;
#pragma mark - Creation
+(id)messageObserverObserving:(id) observable delegate:(id) delegate
{
return [[[PGMessageObserver alloc] initWithObservable:observable delegate:delegate] autorelease];
}
-(id)initWithObservable:(id) observable delegate:(id) delegate
{
if (self = [super init])
{
_observable = observable;
_delegate = delegate;
}
return self;
}
#pragma mark - Message forwarding
-(void)forwardInvocation:(NSInvocation*) invocation
{
//Notify.
[_delegate observedInvocation:invocation willSendToObject:_observable];
//Forward.
if (_observable != nil)
{
[invocation invokeWithTarget:_observable];
//Notify.
[_delegate observedInvocation:invocation didSendToObject:_observable];
}
}
-(NSMethodSignature*)methodSignatureForSelector:(SEL) selector
{
return [_observable methodSignatureForSelector:selector];
}
@end
Il n'est pas aussi strict qu'il pourrait l'être, mais il me notifie chaque action envoyée à cet observateur, et le message est ensuite redirigé vers l'objet original (observable).
Le code client est juste une propriété retenue...
@property (nonatomic, retain) PGMessageObserver *messageObserver;
#define self_OBSERVED _messageObserver
...et une installation quelque part.
self.messageObserver = [PGMessageObserver messageObserverObserving:self delegate:self];
Les messages observables doivent alors être envoyés à SELF_OBSERVED au lieu de self.