2015-12-01 5 views
2

Я работаю над внутренним инструментом (что никогда не будет представлено в App Store), и я бы хотел обнаружить во время выполнения, если класс Objective- C или Swift. Это возможно?iOS Обнаружение, если класс Objective-C или Swift

+1

Какая цель? Если вы обнаружите, что определенный класс - Objective-C или Swift, что вы планируете делать с этой информацией? –

+2

Это проблема XY. Что вы на самом деле пытаетесь сделать и почему? – nhgrif

+0

Я хотел бы знать, можно ли просто удовлетворить свое любопытство. – dreamlax

ответ

1

Названия классов Swift имеют префикс имени модуля. Если один использует:

NSStringFromClass(SomeClass.self) 

Результат будет

MyApp.SomeClass 

Для моей цели, это работает отлично.

+1

Это неправда. Любой класс Swift, аннотированный с помощью @objc, может иметь имя без префикса. Кроме того, имена внутреннего класса Swift могут быть более сложными, чем 'A.B'. – fluidsonic

6

Если для академических целей, вы абсолютно должен знать, если класс был создан в быстрых кодах или нет (и не таким образом, который может быть легко обмануть с помощью objc_allocateClassPair), то вы можете использовать информацию, можно найти в objc-runtime-new.h, в частности, флаги, относящиеся к FAST_IS_SWIFT.

Чтобы извлечь эти флаги без того, чтобы сделать свой исходный код C++ или бороться с включением тонны частных заголовков, вы можете использовать что-то похожее на следующее, но обратите внимание: ЭТО СУПЕР FRAGILE.

Это, вероятно, не применяется нигде, и любая будущая версия может изменить это без последствий. Имейте это в виду, и т.д., и т.д.

Не мудрствуя лукаво, сумасшедший хак вытекает:

#define FAST_IS_SWIFT   (1UL<<0) 
#define FAST_HAS_DEFAULT_RR (1UL<<1) 
#define FAST_DATA_MASK  0xfffffffcUL 

uintptr_t getClassBits(Class kls) { 
#if __LP64__ 
    typedef uint32_t mask_t; 
#else 
    typedef uint16_t mask_t; 
#endif 

    return ((const struct { 
     /* struct objc_class */ 
     Class isa; 
     Class superclass; 

     /* struct cache_t */ 
     void *bucket_t; 
     mask_t mask; 
     mask_t occupied; 

     /* struct class_data_bits_t */ 
     uintptr_t bits; 
    } *) (__bridge const void *) kls)->bits; 
} 

Это воссоздает формат структуры из objc-runtime-new.h, без всех дополнительных накладных расходов C++.

Как только у вас есть бит для класса, просто сравните его с FAST_IS_SWIFT (например, bits & FAST_IS_SWIFT), и у вас должен быть ваш ответ.

 Смежные вопросы

  • Нет связанных вопросов^_^