如何从bundle中获取类

ike*_*8me 3 class objective-c nsbundle ios

按照这里的解释:

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

我试图在捆绑TelephonyUtilities.framework中获取TUPhoneLogger的类.但是,调试器始终显示"错误:未知类".

我有两种不同的方法:

第一种方法:

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

注意:我创建了一个@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);
Run Code Online (Sandbox Code Playgroud)

第二种方法:

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

在调试器中:

在此输入图像描述

Nat*_*ate 7

+1给Victor,因为我认为将Framework作为构建阶段库包含在项目中更简单.私有框架位于PrivateFrameworksSDK子目录下,但除此之外,它的工作方式与公共框架类似(在Victor的答案中描述了差异).

如果你想要动态加载,我将提供另一种有效的技术:

#include <dlfcn.h>
#import <objc/runtime.h>
Run Code Online (Sandbox Code Playgroud)

然后

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

我想有一个好处dlopen()就是你不必记得打电话load,这让你进入了第二个例子.缺点是你应该dlclose()事后打电话.

注意:dlopen() vs NSBundle bundleWithPath:(path 与dir)的路径略有不同

注意++:此代码在模拟器中不起作用,因为模拟器可能缺少该框架(没有真正的手机功能)


更新

在iOS 9.3中,Apple从SDK中删除了Private Frameworks.因此,从那时起,如果Framework不是公共iOS框架之一,通常情况下你需要使用这种动态技术.请参阅此答案了解更多信息