3 votes

Existe-t-il un moyen d'observer tous les appels de messages invoqués sur un objet (iOS) ?

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

4voto

RuiAAPeres Points 14372

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 :

  1. Créez une classe appelée Helper .
  2. Ajoutez une référence à la classe à partir de laquelle vous allez appeler les méthodes, dans ce format : id <HelperDelegate> myClassReference;
  3. Lorsque vous devez faire un [self method] créez plutôt une instance de cette Helper et appeler la méthode sur elle comme [helper method]; et ajoutez ceci [helper setMyClassReference:self]; .
  4. L'application devrait se planter, mais ensuite, il suffit d'ajouter l'élément forwardInvocation: sur le Helper classe. A partir de là, vous pourrez obtenir la NSInvocation 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.

1voto

Geri Points 3572

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.

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