Swizzling eine einzelne Instanz, nicht die Klasse
Habe ich eine Kategorie auf NSObject, die angeblich so einige Dinge. Wenn ich es auf ein Objekt, möchte ich überschreiben Sie die dealloc-Methode hinzu, um einige Aufräumarbeiten.
Wollte ich es mit method swizzling, aber konnte nicht herausfinden, wie. Die einzigen Beispiele, die ich gefunden habe sind auf so ersetzen Sie die Implementierung der Methode für die gesamte Klasse (in meinem Fall wäre es dealloc überschreiben für ALLE NSObjects - was ich nicht will).
Möchte ich überschreiben der dealloc-Methode frei von bestimmten Instanzen von NSObject.
@interface NSObject(MyCategory)
-(void)test;
@end
@implementation NSObject(MyCategory)
-(void)newDealloc
{
//do some cleanup here
[self dealloc]; //call actual dealloc method
}
-(void)test
{
IMP orig=[self methodForSelector:@selector(dealloc)];
IMP repl=[self methodForSelector:@selector(newDealloc)];
if (...) //'test' might be called several times, this replacement should happen only on the first call
{
method_exchangeImplementations(..., ...);
}
}
@end
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie nicht richtig dies tun, da die Objekte nicht über Ihre eigene Methode-Tabellen. Nur haben die Klassen-Methode-Tabellen und, wenn Sie ändern es wird sich auf jedes Objekt der Klasse. Es gibt eine einfache Möglichkeit, um dieses obwohl: Ändern der Klasse des Objekts zur Laufzeit dynamisch erstellt Unterklasse. Diese Technik, die auch als isa-swizzling, ist von Apple verwendet wird, zu implementieren, automatische KVO.
Dies ist eine leistungsfähige Methode, und es hat auch seinen nutzen. Aber für deinen Fall gibt es eine einfachere Methode, mit der zugehörigen Objekte. Im Grunde Sie verwenden
objc_setAssociatedObject
zuordnen ein anderes Objekt, um Ihr erstes Objekt, das macht die Aufräumarbeiten in seinerdealloc
. Sie können weitere details finden Sie im dieser blog-post auf Cocoa ist meine Freundin.NSObject
dass wir Sie registrieren Blöcke aufgerufen werden, während dealloc eines beliebigen Objekts.Methode Auswahl basiert auf den Klasse einer Objekt-Instanz, also Methode swizzling wirkt sich auf alle Instanzen der gleichen Klasse - wie Sie entdeckt.
Aber Sie können ändern Sie die Klasse einer Instanz, aber Sie müssen vorsichtig sein! Hier ist der Umriss, die davon ausgehen, dass Sie eine Klasse:
Nun, wenn nur für einige der Instanzen von
MyPlainObject
Sie möchten, ändern, um das Verhalten vondoSomething
definieren Sie zunächst eine Unterklasse:Nun können Sie deutlich machen, Instanzen von
MyFancyObject
, aber was wir tun müssen ist, nehmen Sie ein bereits bestehenden InstanzMyPlainObject
und machen es zu einemMyFancyObject
so erhalten wir das neue Verhalten. Dafür können wir swizzle der Klasse fügen Sie den folgenden, umMyFancyObject
:Nun für jede original Instanz
MyPlainClass
Sie wechseln können, um sich wie einMyFancyClass
-und Umgekehrt:(Einige) von den Einschränkungen:
Können Sie nur dies tun, wenn die Unterklasse überschreibt oder fügt Methoden hinzu, und fügt
static
(Klassen -) Variablen.Benötigen Sie auch eine sub-Klasse je Klasse, die Sie möchten, ändern Sie das Verhalten, können Sie nicht eine einzelne Klasse, die ändern kann, das Verhalten von vielen verschiedenen Klassen.
Machte ich ein swizzling-API, die auch über die Instanz-spezifischen swizzling. Ich denke, das ist genau das, was du suchst: https://github.com/JonasGessner/JGMethodSwizzler
Es funktioniert durch die Schaffung eines dynamischen Unterklasse für die spezifische Instanz, dass Sie swizzling zur Laufzeit.