如何从捆绑包中获取课程

Posted

技术标签:

【中文标题】如何从捆绑包中获取课程【英文标题】:How to get the class from bundle 【发布时间】:2013-03-13 07:34:34 【问题描述】:

按照这里的解释:

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

我正在尝试在捆绑 TelephonyUtilities.framework 中获取 TUPhoneLogger 的类。但是,调试器总是显示“error: unknown class”

我有两种不同的方法:

第一种方法:

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);

在调试器中:

【问题讨论】:

你没有在第二种方法中调用[b load] 另外,只是从下面重复我的评论......这个框架不会在模拟器上加载,只能在真实(iPhone?)设备上......并且不确定是否是 iPad/iPod Touch也会有这个框架。 【参考方案1】:

+1 致 Victor,因为我认为将框架作为 Build Phase 库包含在您的项目中会更简单。私有框架位于 PrivateFrameworks SDK 子目录下,但除此之外,它的工作方式与公共框架类似(Victor 的回答中描述了不同之处)。

我将提供另一种可行的技术,如果您确实想要动态加载

#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()NSBundle bundleWithPath: 的路径略有不同(文件与目录)

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


更新

在 iOS 9.3 中,Apple 从 SDK 中删除了私有框架。因此,从那时起,如果框架不是公共 iOS 框架之一,实际上通常需要使用这种动态技术。 See this answer for more

【讨论】:

您好,我尝试使用您的方法,仍然是相同的未知类错误。我尝试了您所写的两个内容,还删除了路径末尾的“TelephonyUtilities”。 (我也确实包含了 dlfcn.h) @ikevinjp,它必须有路径末尾的尾随“TelephonyUtilities”。这就是为什么我在帖子末尾写了注意:NSBundle 需要.framework 文件夹,但dlopen() 需要.framework 文件夹内的文件 如果您在模拟器上运行此代码,是的,它会失败,因为模拟器缺少真正的 iPhone 拥有的很多很多东西......显然包括 TelephonyUtilities 框架。但是,如果您在 iPad 或 iPod Touch 上运行,那么可能也缺少该框架。【参考方案2】:

还有第三种方法(我更喜欢)

a) 你静态链接到这个框架(意思是,你将它添加到你的目标)

b) 您在 .h 类中定义了必要的类 (TUPhoneLogger )。你可以通过使用class-dump(-z)来获取它

c) 你包含这个 .h 文件

d) 您只需像使用公共类一样使用私有类。

补充说明

私有框架和私有 API 没有“魔法”。唯一不同的是它们没有被记录并包含在 .h 文件中。

步骤 b) 和 c) 使用它们创建 .h 类,因此它们的使用方式与通常的公共 API 完全相同。

【讨论】:

以上是关于如何从捆绑包中获取课程的主要内容,如果未能解决你的问题,请参考以下文章

Eclipselink:如何在每个捆绑包中获取 EntityManager?

如何借助一对多关系在 Django 中使用外键从课程中获取主题

在运行时替换捆绑包中的图像

如何从laravel中的关系中获取对象

如何列出捆绑包中的所有 KEYS?

第十周课程总结