Klasa celu-C -> ciąg, na przykład: [NSArray className] -> @ „NSArray”

129

Próbuję uzyskać nazwę ciągu klasy z samego obiektu klasy.

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

Znalazłem, object_getClassName(id obj)ale wymaga to przekazania do niego instancji, aw moim przypadku jest to niepotrzebna praca.

Jak więc mogę uzyskać ciąg znaków z obiektu klasy, a nie instancji?

Alex Wayne
źródło

Odpowiedzi:

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

Możesz nawet cofnąć się w drugą stronę:

Class arrayClass = NSClassFromString (name);
id anInstance = [[arrayClass alloc] init];
dreamlax
źródło
Dzięki! Jak jest NSStringFromClasswdrażany? Czy bardziej wydajne jest przechowywanie nazwy klasy w static NSStringzmiennej?
ma11hew28,
13
@MattDiPasquale: Wszystkie nazwy klas są przechowywane gdzieś w środowisku wykonawczym Objective-C (elementy wewnętrzne środowiska wykonawczego są w większości ukryte przed aplikacją i ujawniane tylko przez kilka funkcji API). Każdy obiekt klasy (np. [NSArray class]) Jest w rzeczywistości plikiem struct. structZawiera wiele informacji o klasie, w tym jego nazwy, metody implementuje, superklasę itd NSStringFromClassprostu ciągnie nazwę klasy z tego structi konwertuje go na NSString. Nie przechowuj nazwy klasy w a static NSString, nie zapewni to żadnej korzyści w zakresie wydajności.
dreamlax,
3
@MattDiPasquale: NSClassFromStringdziała trochę inaczej. Ponieważ wszystkie nazwy klas istnieją gdzieś w środowisku wykonawczym Objective-C, NSClassFromStringpobiera ciąg i przegląda listę klas obsługiwanych przez środowisko wykonawcze w poszukiwaniu klasy o podanej nazwie. Jeśli go znajdzie, zwraca go, w przeciwnym razie zwraca Nil.
dreamlax,
2
@MattDiPasquale: "Jak zaimplementowano NSStringFromClass?" jeśli naprawdę chcesz wiedzieć, prawdopodobnie używa class_getName()w czasie wykonywania, co zwraca ciąg C
user102008
2
@AlexZavatone: classNameto metoda dodana przez rozszerzenia skryptów, która jest dostępna tylko w systemie Mac OS X, nawet wtedy jest skomplikowana w działaniu, ponieważ nie jest w pełni udokumentowana (a przynajmniej nie była to ostatnia, gdy sprawdzałem). NSStringFromClass()jest właściwym sposobem rozwiązania tego problemu.
dreamlax
1

Oto inny sposób na zrobienie tego przy nieco mniejszym pisaniu:

NSString *name = [NSArray description];
Sherwin Zadeh
źródło
7
Nie ma gwarancji, że zrobisz to, o co poprosisz. Ta metoda jest często zastępowana w celu zapewnienia opisu obiektu i zawartych w nim danych.
Alex Wayne,
3
Wiem, że jest zastępowana jako metoda INSTANCE, ale jak często jest nadpisywana + description CLASS METHOD? W każdym razie warto się nad tym zastanowić, gdyby nie każda klasa ... Nie sądzę, aby była wymagana obniżka.
Sherwin Zadeh
1
@SherwinZadeh: Myślę, że w praktyce mało prawdopodobne jest znalezienie klas, które zostały zastąpione +description, jednak teoretycznie nie jest to celem +description, więc ta metoda jest delikatna do określania nazw klas.
dreamlax
1

Rozważ tę alternatywę:

const char *name = class_getName(cls);

Jest znacznie szybszy, ponieważ nie musi przydzielać obiektu NSString i konwertować ASCII na jakąkolwiek NSStringreprezentację. Tak NSStringFromClass()jest wdrażane.

cud. mice
źródło
Było to przydatne dla mnie, ale wymagało dodania #import <objc / runtime.h> na początku pliku.
Sparklellama