开发者

How can I get list of classes already loaded into memory in specific bundle (or binary)?

开发者 https://www.devze.com 2023-03-24 06:02 出处:网络
It\'s possible to get list of classes from a bundle via NSBundleDidLoadNotification. But I can\'t figure out how I can ge开发者_如何学JAVAt them from already loaded bundle. (same bundle with code)

It's possible to get list of classes from a bundle via NSBundleDidLoadNotification. But I can't figure out how I can ge开发者_如何学JAVAt them from already loaded bundle. (same bundle with code)

I'm trying to get class list of my application bundle. More specifically, the classes only in my application binary.

I looked at objc_getClassList, but it returns ALL classes and it's obviously too heavy for me. I need lightweight method. I found objc_copyClassNamesForImage by googling, but it's not documented, and I don't know how to use it safely. I think I can try to use it conventionally, but I want to find another more safe option before going there.


Another option would be to iterate through all the classes registered with the runtime and use +[NSBundle bundleForClass:] on each one to figure out which one it came from. You can then sort things into sets based on the result.

Something like this:

@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

Then you can call:

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


Try this magic:

- (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;
}


I could find some example for the function objc_copyClassNamesForImage at here.

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

The source code is unofficial but from Apple. So I decided to use this code until I find any better way.

0

精彩评论

暂无评论...
验证码 换一张
取 消