3

按照这里的解释:

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

在调试器中:

在此处输入图像描述

4

2 回答 2

7

+1 给 Victor,因为我认为将框架作为构建阶段库包含在您的项目中更简单。私有框架位于PrivateFrameworksSDK 子目录下,但除此之外,它的工作方式与公共框架类似(在 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() vs NSBundle bundleWithPath:(文件与目录)的路径略有不同

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


更新

在 iOS 9.3 中,Apple 从 SDK 中删除了私有框架。因此,从那时起,如果框架不是公共 iOS 框架之一,实际上通常需要使用这种动态技术。有关更多信息,请参阅此答案

于 2013-03-14T23:20:12.217 回答
2

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

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

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

c) 你包含这个 .h 文件

d)您只需像使用公共课程一样使用私人课程。

小补充说明

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

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

于 2013-03-13T14:47:51.073 回答