Frage

Kann ich abfangen eine Call-Methode in Objective-C? Wie?

Edit: Mark Powell 's Antwort gab mir eine Teillösung, die -forwardInvocation Methode. Aber die Dokumentation besagt, dass -forwardInvocation nur aufgerufen, wenn ein Objekt eine Nachricht gesendet wird, für die es kein entsprechendes Verfahren hat. Ich würde eine Methode, wie unter allen Umständen genannt werden, auch wenn der Empfänger hat, dass die Wähler.

War es hilfreich?

Lösung

Sie tun es durch den Methodenaufruf Swizzling. Angenommen, Sie möchten, dass alle Versionen NSTableView greifen:

static IMP gOriginalRelease = nil;
static void newNSTableViewRelease(id self, SEL releaseSelector, ...) {
   NSLog(@"Release called on an NSTableView");
   gOriginalRelease(self, releaseSelector);
}


  //Then somewhere do this:
  gOriginalRelease = class_replaceMethod([NSTableView class], @selector(release), newNSTableViewRelease, "v@:");

Sie können mehr Details in der Objective-C-Laufzeit erhalten Dokumentation .

Andere Tipps

Intercepting Methode ruft in Objective-C (asuming es ist ein Objective-C, keine C-Aufruf) mit einer Technik gemacht namens Methode Swizzling.

Sie können eine Einführung finden auf, wie das hier rel="nofollow zu implementieren. Ein Beispiel, wie Verfahren Swizzling in einem realen Projekt implementiert überprüfen OCMock (ein Isolation Rahmen für Objective-C).

Senden einer Nachricht in Objective-C in einem Aufruf der Funktion objc_msgSend(receiver, selector, arguments) übersetzt wird oder eine seiner Varianten objc_msgSendSuper, objc_msgSend_stret, objc_msgSendSuper_stret.

Wenn es möglich war, die Umsetzung dieser Funktionen zu ändern, könnten wir jede Nachricht abfangen. Leider objc_msgSend Teil der Objective-C-Laufzeit ist und nicht außer Kraft gesetzt werden kann.

I von googeln ein Papier über Google Books: A Reflective Architecture for Process Control Applications von Charlotte Pii Lunau . Das Papier stellt einen Hack durch ein isa Klasse Zeiger auf eine Instanz einer benutzerdefinierten metaObject Klasse des Objekts umgeleitet wird. Nachrichten, die für das modifizierte Objekt bestimmt wurden, werden daher die Metaobjekt Instanz gesendet. Da die metaObject Klasse keine eigenen Methoden hat, kann er dann auf den Vorwärts Aufruf reagieren, indem sie die Nachricht an das geänderte Objekt weitergeleitet werden.

Das Papier enthält nicht die interessanten Bits des Quellcodes und ich habe keine Ahnung, ob ein solcher Ansatz Nebenwirkungen in Cocoa haben würde. Aber es könnte interessant sein, zu versuchen.

Wenn Sie Nachricht von Ihrem Anwendungscode anmelden sendet, die -forwardingTargetForSelector: Spitze ist ein Teil der Lösung
. Wickeln Sie Ihr Objekt:

@interface Interceptor : NSObject
@property (nonatomic, retain) id interceptedTarget;
@end

@implementation Interceptor
@synthesize interceptedTarget=_interceptedTarget;

- (void)dealloc {
    [_interceptedTarget release];
    [super dealloc];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"Intercepting %@", NSStringFromSelector(aSelector));
    return self.interceptedTarget;
} 

@end

Jetzt etwas tun, wie folgt aus:

Interceptor *i = [[[Interceptor alloc] init] autorelease];
NSFetchedResultsController *controller = [self setupFetchedResultsController];
i.interceptedTarget = controller;
controller = (NSFetchedResultsController *)i;

und Sie haben ein Protokoll der Nachricht sendet. Beachten Sie, sendet aus dem abgefangenen Objekt gesendet wird nicht abgefangen werden, da sie das ursprüngliche Objekt ‚Selbst‘ Zeiger gesendet werden.

Wenn Sie nur Nachrichten von außen aufgerufen einzuloggen (in der Regel von den Delegierten genannt, zu sehen, welche Art von Nachrichten, wenn usw.), können Sie respondsToSelector wie dies außer Kraft setzen:

- (BOOL)respondsToSelector:(SEL)aSelector {
NSLog(@"respondsToSelector called for '%@'", NSStringFromSelector(aSelector));

// look up, if a method is implemented
if([[self class] instancesRespondToSelector:aSelector]) return YES;

return NO;

}

Erstellen Sie eine Unterklasse von NSProxy und implementieren -forwardInvocation: und -methodSignatureForSelector: (oder -forwardingTargetForSelector: , wenn Sie ‚re lenken sie einfach auf ein zweites Objekt statt mit dem Verfahren von Hantieren selbst).

NSProxy ist eine Klasse für die Implementierung -forwardInvocation: entwarfen auf. Es hat ein paar Methoden, aber vor allem wollen Sie sie nicht gefangen werden. Zum Beispiel würde die Referenz Zählverfahren Fang verhindert den Proxy vor einer Zuordnung aufgehoben außer unter garbage collection. Aber wenn es bestimmte Methoden auf NSProxy, die Sie unbedingt weiterleiten müssen, können Sie diese Methode überschreiben, gezielt und rufen -forwardInvocation: manuell. Sie beachten Sie, dass, nur weil ein Verfahren unter der NSProxy Dokumentation aufgeführt ist, bedeutet nicht, dass NSProxy es implementiert, lediglich, dass es wird erwartet, dass alle Proxy-Objekte haben es.

Wenn dies nicht für Sie arbeitet, sorgt für zusätzliche Details über Ihre Situation.

Vielleicht möchten Sie NSObject die -forwardInvocation Methode. Auf diese Weise können Sie eine Nachricht erfassen, retarget es und dann erneut zu senden.

Sie können den Methodenaufruf mit einem Ihrer eigenen swizzle, das tut, was Sie auf „Abfangen“ tun wollen und ruft die ursprüngliche Implementierung durch. Swizzling mit class_replaceMethod getan ().

Ein Methodenaufruf, Nr. Eine Nachricht senden, ja, aber du gehst zu haben, viel mehr beschreibend sein, wenn Sie eine gute Antwort auf die Frage, wie wollen.

Um etwas zu tun, wenn eine Methode aufgerufen wird, können Sie ein Ereignis basierten Ansatz versuchen. Also, wenn die Methode aufgerufen wird, sendet es ein Ereignis, das bis von allen Zuhörern gerichtet. Ich bin nicht gut mit Objective-C, aber ich gerade etwas Ähnliches heraus mit NSNotificationCenter in Cocoa.

Aber wenn durch „Intercept“ Sie bedeuten, „Stop“, dann vielleicht Sie mehr Logik müssen, ob das Verfahren zu entscheiden, sollte überhaupt genannt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top