I want to get all the native classes (NSString, NSNumber, int, float, NSSet, NSDictionary) that I have loaded into my iOS Project..
i.e., if I have created a custom class named "TestClass" I don't want it listed...
I have already got a code but it returns names of all classes loaded any way I can modify the code to limit the list to Native classes only?
#import <objc/runtime.h>
#import <dlfcn.h>
#import <mach-o/ldsyms.h>
unsigned int count;
const char **classes;
Dl_info info;
dladdr(&_mh_execute_header, &info);
classes = objc_copyClassNamesForImage(info.dli_fname, &count);
for (int i = 0; i < count; i++) {
NSLog(@"Class name: %s", classes[i]);
Class class = NSClassFromString ([NSString stringWithCString:classes[i] encoding:NSUTF8StringEncoding]);
// Do something with class
}
You would get all loaded classes with
int numClasses;
Class * classes = NULL;
classes = NULL;
numClasses = objc_getClassList(NULL, 0);
if (numClasses > 0 )
{
classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);
for (int i = 0; i < numClasses; i++) {
Class c = classes[i];
NSLog(@"%s", class_getName(c));
}
free(classes);
}
(Code from objc_getClassList documentation.)
To restrict the list, you can check the bundle from which the class was loaded, e.g.
Class c = classes[i];
NSBundle *b = [NSBundle bundleForClass:c];
if (b != [NSBundle mainBundle])
...
for all classes that are not loaded from your application.
Here's a pure Swift solution with Swift 3:
var numClasses: Int32 = 0
var allClasses: AutoreleasingUnsafeMutablePointer<AnyClass?>? = nil
defer {
allClasses = nil
}
numClasses = objc_getClassList(nil, 0)
if numClasses > 0 {
var ptr = UnsafeMutablePointer<AnyClass?>.allocate(capacity: Int(numClasses))
defer {
ptr.deinitialize()
ptr.deallocate(capacity: Int(numClasses))
}
allClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>(ptr)
numClasses = objc_getClassList(allClasses, numClasses)
for i in 0 ..< numClasses {
if let currentClass: AnyClass = allClasses?[Int(i)] {
print("\(currentClass)")
}
}
}
Original solution with Swift 2.2/Xcode 7.3:
var numClasses: Int32 = 0
var allClasses: AutoreleasingUnsafeMutablePointer<AnyClass?> = nil
defer {
allClasses = nil
}
numClasses = objc_getClassList(nil, 0)
if numClasses > 0 {
var ptr = UnsafeMutablePointer<AnyClass>.alloc(Int(numClasses))
defer {
ptr.destroy()
ptr.dealloc(Int(numClasses))
ptr = nil
}
allClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>.init(ptr)
numClasses = objc_getClassList(allClasses, numClasses)
for i in 0 ..< numClasses {
if let currentClass: AnyClass = allClasses[Int(i)] {
print("\(currentClass)")
}
}
}
Note that due to the way Swift handles weak pointers (protip: it doesn't), your classes will be overreleased with this code. I've opened SR-1068 about bridging __weak
and __unsafe_unretained
pointers to Swift. __weak
pointers are bridged as UnsafeMutablePointer
while __unsafe_unretained
pointers are bridged as AutoreleasingUnsafeMutablePointer
, which causes the overrelase.
Fortunately, Classes don't do anything on release, so this code is relatively safe, at least for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With