Как получить класс из пакета



После объяснения здесь:



Https://github.com/nst/iOS-Runtime-Headers



Я пытаюсь получить класс TUPhoneLogger в комплекте TelephonyUtilities.рамки. Однако отладчик всегда показывает "ошибка: неизвестный класс" .



у меня есть 2 различных метода:



Первый метод:



NSBundle* b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/TelephonyUtilities.framework"];
BOOL success = [b load];
NSLog(@"%@", [b definedClasses_dd]);


Примечание: я создал @interface NSBundle (DDAdditions)
расширение:



- (NSArray *)definedClasses_dd {
NSMutableArray *array = [NSMutableArray array];
int numberOfClasses = objc_getClassList(NULL, 0);
Class *classes = calloc(sizeof(Class), numberOfClasses);
numberOfClasses = objc_getClassList(classes, numberOfClasses);
for (int i = 0; i < numberOfClasses; ++i) {
Class c = classes[i];
if ([NSBundle bundleForClass:c] == self) {
[array addObject:c];
const char* nameOfClass = class_getName(c);
NSString* classString = [NSString stringWithUTF8String:nameOfClass];
if([classString isEqualToString:@"TUPhoneLogger"]) {
NSLog(@"Found it! TUPhoneLogger");
id test= [[c alloc] init];
NSLog(@"test: %@", test);
}
}
}
free(classes);


Второе метод:



NSBundle* b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/TelephonyUtilities.framework"];
Class telephonyClass = [b classNamed:@"TUPhoneLogger"];
id test= [[telephonyClass alloc] init];
NSLog(@"%@", test);


В отладчике:



Введите описание изображения здесь

617   2  

2 ответов:

Есть третий метод (который я предпочитаю)

A) вы статически связываетесь с этим фреймворком (то есть вы добавляете его к своей цели)

B) вы определяете необходимый класс (TUPhoneLogger) в .h класс. Вы можете получить его с помощью class-dump (- z)

C) вы включаете это .H file

D) вы просто используете частный класс так же, как вы используете открытый класс.

Небольшое дополнительное объяснение

В частных фреймворках и частных API нет никакой "магии". Единственный отличается тем, что они не документированы и не включены .H файлов.

Шаг b) и c) создает .H классов с ними и в результате они могут быть использованы точно так же, как обычный публичный API.

+1 к Виктору, поскольку я думаю, что проще просто включить фреймворк в качестве библиотекифазы сборки в свой проект. Частные фреймворки находятся в подкаталоге PrivateFrameworks SDK, но в остальном они работают так же, как и публичные фреймворки (с различиями, описанными в ответе Виктора).

Я просто предложу еще один метод, который работает, Если вы хотите динамическую загрузку :

#include <dlfcn.h>
#import <objc/runtime.h>

И затем

void* handle = dlopen("/System/Library/PrivateFrameworks/TelephonyUtilities.framework/TelephonyUtilities", RTLD_NOW);
Class c = NSClassFromString(@"TUPhoneLogger");
id instance = [[c alloc] init];
dlclose(handle);

Я полагаю, что преимущество dlopen() состоит в том, что вы не нужно помнить о вызове load, который вы получили во втором примере. Недостатком является то, что вы должны позвонить dlclose() после этого.

Примечание: небольшая разница в пути для dlopen() vs NSBundle bundleWithPath: (file vs dir)

Примечание++: этот код не будет работать в симуляторе, так как в симуляторе, вероятно, отсутствует этот фреймворк (нет реальной функциональности телефона)


Обновление

В iOS 9.3 Apple удалила частные фреймворки из SDK. Так вот, с тех пор это на самом деле обычно бывает так, что вам нужно будет использовать эту динамическую технику, если фреймворк не является одним из общедоступных фреймворков iOS. смотрите этот ответ Подробнее

Comments

    Ничего не найдено.