Da ich in Objective-C keine synthetisierte Eigenschaft in einer Kategorie erstellen kann, kann ich den folgenden Code nicht optimieren:
@interface MyClass (Variant)
@property (nonatomic, strong) NSString *test;
@end
@implementation MyClass (Variant)
@dynamic test;
- (NSString *)test {
NSString *res;
//do a lot of stuff
return res;
}
@end
Die Testmethode wird zur Laufzeit mehrmals aufgerufen und ich mache eine Menge Dinge, um das Ergebnis zu berechnen. Normalerweise speichere ich den Wert unter Verwendung einer synthetisierten Eigenschaft beim ersten Aufruf der Methode in einem IVar-Test und gebe diesen IVar beim nächsten Mal zurück. Wie kann ich den obigen Code optimieren?
objective-c
categories
dhrm
quelle
quelle
Antworten:
Die Methode von @ lorean funktioniert (Hinweis: Die Antwort ist jetzt gelöscht) , aber Sie haben nur einen einzigen Speicherplatz. Wenn Sie dies also für mehrere Instanzen verwenden möchten und jede Instanz einen bestimmten Wert berechnen möchte, funktioniert dies nicht.
Glücklicherweise hat die Objective-C-Laufzeit dieses Ding namens Associated Objects , das genau das tun kann, was Sie wollen:
quelle
@selector(test)
als Schlüssel entfernen.h-Datei
.m-Datei
Genau wie eine normale Eigenschaft - zugänglich mit Punktnotation
Einfachere Syntax
Alternativ können Sie
@selector(nameOfGetter)
anstelle eines statischen Zeigerschlüssels Folgendes verwenden:Weitere Informationen finden Sie unter https://stackoverflow.com/a/16020927/202451
quelle
@dynamic objectTag;
.@dynamic
bedeutet, dass der Setter & Getter woanders generiert wird, aber in diesem Fall werden sie genau hier implementiert.Die gegebene Antwort funktioniert großartig und mein Vorschlag ist nur eine Erweiterung, die vermeidet, zu viel Code auf dem Boilerplate zu schreiben.
Um zu vermeiden, dass wiederholt Getter- und Setter-Methoden für Kategorieeigenschaften geschrieben werden, werden in dieser Antwort Makros eingeführt. Zusätzlich erleichtern diese Makros die Verwendung primitiver Typeneigenschaften wie
int
oderBOOL
.Traditioneller Ansatz ohne Makros
Traditionell definieren Sie eine Kategorieeigenschaft wie
Dann müssen Sie eine Getter- und Setter-Methode implementieren, die ein zugehöriges Objekt und den Get-Selektor als Schlüssel verwendet ( siehe ursprüngliche Antwort ):
Mein vorgeschlagener Ansatz
Mit einem Makro schreiben Sie stattdessen:
Die Makros sind wie folgt definiert:
Das Makro
CATEGORY_PROPERTY_GET_SET
fügt einen Getter und einen Setter für die angegebene Eigenschaft hinzu. Read-only oder Nur - Schreib-Eigenschaften werden die VerwendungCATEGORY_PROPERTY_GET
undCATEGORY_PROPERTY_SET
jeweils Makro.Primitive Typen brauchen etwas mehr Aufmerksamkeit
Da primitive Typen keine Objekte sind, enthalten die obigen Makros ein Beispiel für die Verwendung
unsigned int
als Eigenschaftstyp. Dazu wird der ganzzahlige Wert in einNSNumber
Objekt eingeschlossen. Die Verwendung ist also analog zum vorherigen Beispiel:Nach diesem Muster können Sie einfach mehr Makros auch hinzufügen , zu unterstützen
signed int
,BOOL
usw ...Einschränkungen
Alle Makros werden
OBJC_ASSOCIATION_RETAIN_NONATOMIC
standardmäßig verwendet.IDEs wie App Code erkennen derzeit den Namen des Setters nicht, wenn der Name der Eigenschaft umgestaltet wird. Sie müssten es selbst umbenennen.
quelle
#import <objc/runtime.h>
in der Kategorie .m Datei sonst. Fehler bei der Kompilierung: Die implizite Deklaration der Funktion 'objc_getAssociatedObject' ist in C99 ungültig . stackoverflow.com/questions/9408934/…Verwenden Sie einfach die Bibliothek libextobjc :
h-Datei:
m-Datei:
Weitere Informationen zu @synthesizeAssociation
quelle
Nur mit iOS 9 getestet Beispiel: Hinzufügen einer UIView-Eigenschaft zu UINavigationBar (Kategorie)
UINavigationBar + Helper.h
UINavigationBar + Helper.m
quelle
Eine andere mögliche, vielleicht einfachere Lösung, die nicht verwendet
Associated Objects
wird, besteht darin, eine Variable in der Kategorieimplementierungsdatei wie folgt zu deklarieren:Der Nachteil dieser Art der Implementierung ist, dass das Objekt nicht als Instanzvariable, sondern als Klassenvariable fungiert. Außerdem können Eigenschaftsattribute nicht zugewiesen werden (wie sie in zugeordneten Objekten wie OBJC_ASSOCIATION_RETAIN_NONATOMIC verwendet werden).
quelle