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

Eon*_*nil 7 cocoa cocoa-touch objective-c ios

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

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

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

Dav*_*ong 5

另一种选择是迭代在运行时注册的所有类,并使用+[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
Run Code Online (Sandbox Code Playgroud)

然后你可以调用:

NSLog(@"%@", [[NSBundle mainBundle] definedClasses_dd]);
Run Code Online (Sandbox Code Playgroud)


mal*_*hal 5

试试这个魔法:

- (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;
}
Run Code Online (Sandbox Code Playgroud)


Eon*_*nil 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);
Run Code Online (Sandbox Code Playgroud)

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