6

Ich versuche herauszufinden, wie die Dinge wirklich funktionieren. Also dachte ich, wenn ich bestimmte Methoden mit Kategorien überschreiben würde, würde ich interessante NSLogs bekommen.Wie wird die ursprüngliche Implementierung beim Überschreiben einer Methode mit einer Kategorie aufgerufen?

@implementation UIView(Learning) 
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    NSLog(@"-hitTest:withEvent: event=%@", event); 
    return [self hitTest:point withEvent:event]; 
} 
@end 

Super und Selbst funktionieren hier nicht. Gibt es eine Möglichkeit, die ursprüngliche Implementierung von -hitTest aufzurufen: withEvent :? Was ich will ist ein NSLog jedes Mal - hitTest: withEvent: wird auf einer UIView aufgerufen.

Es ist nur für persönliche Lernzwecke. Ich möchte die Ereignislieferung in Aktion sehen.

+0

Super-nicht, weil Sie in einer Kategorie arbeiten‘ Wenn du es nicht in der gleichen Klasse anrufst, nennst du es im Super der Klasse. In diesem Fall ist der Super ein UIResponder, der keine Methode hitTest: withEvent hat. Der Aufruf von self führt nur zu einer Endlosschleife, weil Sie hitTest überschreiben: withEvent für "self". –

+0

Mein Kommentar sieht hier ein wenig fehl am Platz, aber es machte Sinn, bevor der vorhergehende kommentierte seinen gelöscht. –

Antwort

14

Sie es tun können, aber nicht eine Kategorie verwenden. Eine Kategorie ersetzt eine Methode. (Warnung, Auto Analogie) Wenn Sie ein Auto haben, und Sie zerstören dieses Auto und ersetzen Sie es mit einem neuen Auto, können Sie noch das alte Auto benutzen? Nein, weil es weg ist und nicht mehr existiert. Dasselbe mit Kategorien.

Was könnten Sie tun, ist verwenden, um die Objective-C-Laufzeit des Verfahrens unter einem anderen Namen zur Laufzeit (sagen wir, „bogusHitTest:withEvent:“), dann tauschen Sie die Implementierungen von hitTest:withEvent: und bogusHitTest:withEvent: hinzuzufügen. Wenn der Code hitTest:withEvent: aufruft, wird der Code ausgeführt, der ursprünglich für bogusHitTest:withEvent: geschrieben wurde. Sie können dann diesen Code aufrufen bogusHitTest:withEvent:, die die ursprüngliche Implementierung ausführen wird.

So ist die falsche Methode würde wie folgt aussehen:

- (UIView *) bogusHitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    NSLog(@"executing: %@", NSStringFromSelector(_cmd)); 
    return [self bogusHitTest:point withEvent:event]; 
} 

Der Code die Methoden auszutauschen wäre etwas entlang der Linien von:

Method bogusHitTest = class_getInstanceMethod([UIView class], @selector(bogusHitTest:withEvent:)); 
Method hitTest = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:)); 
method_exchangeImplementations(bogusHitTest, hitTest); 
+0

Großartig. Kurz. Funktioniert. Vielen Dank! –

0

Leider gibt es keine Möglichkeit, die ursprüngliche Implementierung einer Methode aufzurufen, die Sie überschreiben. Sobald Sie es in der Kategorie implementieren, haben Sie die ursprüngliche Methode beseitigt.

Das Senden derselben Nachricht an super sollte in Ihrer Methode funktionieren; Es wird die Methode der Oberklasse als normal aufrufen (falls es eine gibt).

Das Senden der gleichen Nachricht an self wird eine Endlosschleife erstellen, wie Sie sicherlich schon festgestellt haben.

+1

Wie Adam gesagt hat, ist dies auf diese Weise nicht möglich, aber Sie könnten sich Method Swizzling ansehen. Es gibt ein großartiges Beispiel hier: http://github.com/marksands/UITextViewLinkOptions –

3

Was Sie tun möchten, ist Methode Swizzling genannt: http://www.cocoadev.com/index.pl?MethodSwizzling

+0

Ich bin mir nicht sicher, aber der Artikel scheint ein wenig veraltet zu sein. Dave DeLong hat eine Lösung veröffentlicht, die ziemlich gut mit weniger Code funktioniert. Danke trotzdem :-) –

+0

@BugAlert nur damit du weißt, mein Code * ist * Methode swizzling. Der verlinkte Artikel hat nur viel mehr Informationen darüber. :) –

Verwandte Themen