Клас Objective-C -> рядок типу: [NSArray className] -> @ "NSArray"


128

Я намагаюся отримати ім'я рядка класу від самого об’єкта класу.

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

Я знайшов, object_getClassName(id obj)але для цього потрібен екземпляр, і в моєму випадку це зайва робота.

Тож як я можу отримати рядок від об’єкта класу, а не екземпляра?

Відповіді:


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

Можна навіть повернутися іншим шляхом:

Class arrayClass = NSClassFromString (name);
id anInstance = [[arrayClass alloc] init];

Дякую! Як NSStringFromClassреалізується? Чи ефективніше зберігати ім’я класу у static NSStringзмінній?
ma11hew28

13
@MattDiPasquale: Усі назви класів зберігаються десь у режимі виконання Objective-C (внутрішні місця виконання в основному приховані від програми та опромінені лише через декілька функцій API). Кожен об’єкт класу (наприклад [NSArray class]) є насправді a struct. Він structмістить багато інформації про клас, включаючи його ім'я, методи, які він реалізує, надклас тощо. NSStringFromClassПросто витягує з цього імені класу structі перетворює його в an NSString. Не зберігайте назву класу в static NSString, це не надасть переваги продуктивності.
dreamlax

3
@MattDiPasquale: NSClassFromStringпрацює трохи інакше. Оскільки всі назви класів існують десь у режимі виконання Objective-C, NSClassFromStringприймає рядок та досліджує список класів, що підтримуються під час виконання, шукаючи клас, який має дане ім'я. Якщо він знайде його, він поверне його, інакше повернеться Nil.
dreamlax

2
@MattDiPasquale: "Як реалізується NSStringFromClass?" якщо ви дійсно хочете знати, він, ймовірно, використовує class_getName()під час виконання, який повертає рядок C
user102008

2
@AlexZavatone: classNameце метод, доданий розширеннями сценаріїв, який доступний лише на Mac OS X, навіть тоді він витончений у тому, як це працює, тому що він не повністю задокументований (або, принаймні, це не був останній раз, коли я перевіряв). NSStringFromClass()це правильний шлях для цього.
dreamlax

1

Ось інший спосіб зробити це з трохи меншим типом:

NSString *name = [NSArray description];

7
Це не гарантовано виконувати те, що просять. Цей метод зазвичай перекривається, щоб надати опис об'єкта та даних, які він містить.
Алекс Уейн

3
Я знаю, що це відмінено як метод ІНСТАНЦІЇ, але як часто перекривається метод опису + опис класу? У будь-якому випадку варто подумати, якщо не для кожного класу ... Я не думаю, що до пониження потрібне не було.
Шервін Заде

1
@SherwinZadeh: Я думаю, що на практиці ви навряд чи знайдете класи, які перекрили +description, однак, теоретично це не є метою +description, і тому цей метод є крихким для визначення назв класів.
dreamlax

1

Розглянемо цю альтернативу:

const char *name = class_getName(cls);

Це набагато швидше, оскільки йому не потрібно виділяти об'єкт NSString і перетворювати ASCII в будь-яке NSStringпредставлення. Ось як NSStringFromClass()реалізується.


Це було корисно для мене, але потрібно було додати #import <objc / runtime.h> у верхній частині файлу.
Спарклеллама
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.