如何获取已经加载到特定包(或二进制)内存中的类列表?

时间:2011-07-31 03:58:48

标签: objective-c ios cocoa-touch cocoa

可以通过NSBundleDidLoadNotification从包中获取类列表。但我无法弄清楚如何从已经加载的包中获取它们。 (与代码相同的捆绑包)

我正在尝试获取应用程序包的类列表。更具体地说,这些类只在我的应用程序二进制文件中。

我查看了objc_getClassList,但它返回所有类,对我来说显然太重了。我需要轻量级的方法。我通过Google搜索找到了objc_copyClassNamesForImage,但没有记录,我不知道如何安全使用它 。我想我可以尝试按常规使用它,但我想在去那里之前找到另一个更安全的选择。

3 个答案:

答案 0 :(得分:4)

另一种选择是迭代遍历运行时注册的所有类,并在每个类上使用+[NSBundle bundleForClass:]来确定它来自哪一个。然后,您可以根据结果将事物分组。

这样的事情:

@interface NSBundle (DDAdditions)

- (NSArray *)definedClasses_dd;

@end

@implementation 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];
        }
    }
    free(classes);
    return array;
}

@end

然后你可以打电话:

NSLog(@"%@", [[NSBundle mainBundle] definedClasses_dd]);

答案 1 :(得分:4)

试试这个魔法:

-(NSArray*)getClassNames{
    NSMutableArray* classNames = [NSMutableArray array];
    unsigned int count = 0;
    const char** classes = objc_copyClassNamesForImage([[[NSBundle mainBundle] executablePath] UTF8String], &count);
    for(unsigned int i=0;i<count;i++){
        NSString* className = [NSString stringWithUTF8String:classes[i]];
        [classNames addObject:className];
    }
    return classNames;
}

答案 2 :(得分:1)

我可以在这里找到函数objc_copyClassNamesForImage的一些示例。

http://www.opensource.apple.com/source/objc4/objc4-493.9/test/weak.m

// class name list
const char *image = class_getImageName(objc_getClass("NotMissingRoot"));
testassert(image);
const char **names = objc_copyClassNamesForImage(image, NULL);
testassert(names);
testassert(classInNameList(names, "NotMissingRoot"));
testassert(classInNameList(names, "NotMissingSuper"));
if (weakMissing) {
    testassert(! classInNameList(names, "MissingRoot"));
    testassert(! classInNameList(names, "MissingSuper"));
} else {
    testassert(classInNameList(names, "MissingRoot"));
    testassert(classInNameList(names, "MissingSuper"));
}
free(names);

源代码是非官方的,但来自Apple。所以我决定使用这段代码,直到找到更好的方法。