Objective-C-Klasse -> Zeichenfolge wie: [NSArray className] -> @ “NSArray”

128

Ich versuche, einen Zeichenfolgennamen einer Klasse aus dem Klassenobjekt selbst abzurufen.

// For instance
[NSArray className]; // @"NSArray"

Ich habe festgestellt, object_getClassName(id obj)aber dafür muss eine Instanz übergeben werden, und in meinem Fall ist das unnötige Arbeit.

Wie kann ich also eine Zeichenfolge aus einem Klassenobjekt und nicht aus einer Instanz abrufen?

Alex Wayne
quelle

Antworten:

305
NSString *name = NSStringFromClass ([NSArray class]);

Sie können sogar in die andere Richtung zurückkehren:

Class arrayClass = NSClassFromString (name);
id anInstance = [[arrayClass alloc] init];
Dreamlax
quelle
Vielen Dank! Wie wird NSStringFromClassumgesetzt? Ist es performanter, den Klassennamen in einer static NSStringVariablen zu speichern ?
ma11hew28
13
@MattDiPasquale: Alle Klassennamen werden irgendwo in der Objective-C-Laufzeit gespeichert (die Interna der Laufzeit sind größtenteils vor der Anwendung verborgen und werden nur über einige API-Funktionen verfügbar gemacht). Jedes Klassenobjekt (zB [NSArray class]) ist tatsächlich ein struct. Das structenthält viele Informationen über die Klasse, einschließlich ihres Namens, der implementierten Methoden, der Oberklasse usw., NSStringFromClasszieht einfach den Namen der Klasse daraus structund konvertiert ihn in einen NSString. Speichern Sie den Klassennamen nicht in a static NSString, da dies keinen Leistungsvorteil bietet.
Dreamlax
3
@MattDiPasquale: NSClassFromStringfunktioniert etwas anders. Da alle Klassennamen irgendwo in der Objective-C-Laufzeit vorhanden sind, NSClassFromStringwird die Zeichenfolge verwendet und die Liste der von der Laufzeit verwalteten Klassen durchsucht, um nach der Klasse mit dem angegebenen Namen zu suchen. Wenn es es findet, gibt es es zurück, andernfalls gibt es zurück Nil.
Dreamlax
2
@MattDiPasquale: "Wie wird NSStringFromClass implementiert?" Wenn Sie es wirklich wissen wollen, wird es wahrscheinlich class_getName()in der Laufzeit verwendet, die einen C-String
zurückgibt
2
@AlexZavatone: classNameist eine Methode, die von den Skripterweiterungen hinzugefügt wurde und nur unter Mac OS X verfügbar ist. Selbst dann ist die Funktionsweise schwierig, da sie nicht vollständig dokumentiert ist (oder zumindest nicht das letzte Mal, dass ich sie überprüft habe). NSStringFromClass()ist der richtige Weg, um es zu tun.
Dreamlax
1

Hier ist eine andere Möglichkeit, dies mit etwas weniger Eingabe zu tun:

NSString *name = [NSArray description];
Sherwin Zadeh
quelle
7
Es ist nicht garantiert, dass das getan wird, was verlangt wird. Diese Methode wird häufig überschrieben, um eine Beschreibung des Objekts und der darin enthaltenen Daten bereitzustellen.
Alex Wayne
3
Ich weiß, dass es als INSTANCE-Methode überschrieben wird, aber wie oft wird die + description CLASS METHOD überschrieben? Auf jeden Fall lohnt es sich zu überlegen, ob nicht für jede Klasse ... Ich glaube nicht, dass ein Downgrade erforderlich war.
Sherwin Zadeh
1
@SherwinZadeh: Ich denke, in der Praxis ist es unwahrscheinlich, dass Sie Klassen finden, die überschrieben +descriptionwurden. Theoretisch ist dies jedoch nicht der Zweck +description, und daher ist diese Methode für die Bestimmung von Klassennamen fragil.
Dreamlax
1

Betrachten Sie diese Alternative:

const char *name = class_getName(cls);

Es ist viel schneller, da es kein NSString-Objekt zuordnen und ASCII in eine beliebige NSStringDarstellung konvertieren muss . So NSStringFromClass()wird es umgesetzt.

Wonder.mice
quelle
Dies war nützlich für mich, musste aber #import <objc / runtime.h> am Anfang der Datei hinzufügen.
Sparklellama