Find ALL cocoa classes that are single?
There are several system classes in Cocoa that are singleton like UIApplication, NSNotificationCenter. Now, I want to find all classes that are singleton, any guess how can I quickly find them all?
I'm working on a huge codebase and I need to decouple the singleton object from the custom singleton.
source to share
Objective-C Runtime Hacking! Fun!
Now, before proceeding, I will introduce a disclaimer that I would never recommend putting anything like this in the actual shipping code, and if you do, it is completely not my fault. It can be fun / interesting for educational purposes.
This would not be an exact science as the language itself does not have any real concept of "singleton". Basically, we are just looking for Objective-C classes that have class methods with certain price list prefixes. If we find one of these, there's a good chance we have a singleton.
With this in mind:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
static BOOL ClassIsSingleton(Class class) {
unsigned int methodCount = 0;
Method *methods = class_copyMethodList(object_getClass(class), &methodCount);
@try {
for (unsigned int i = 0; i < methodCount; i++) {
Method eachMethod = methods[i];
// only consider class methods with no arguments
if (method_getNumberOfArguments(eachMethod) != 2) {
continue;
}
char *returnType = method_copyReturnType(eachMethod);
@try {
// only consider class methods that return objects
if (strcmp(returnType, @encode(id)) != 0) {
continue;
}
}
@finally {
free(returnType);
}
NSString *name = NSStringFromSelector(method_getName(methods[i]));
// look for class methods with telltale prefixes
if ([name hasPrefix:@"shared"]) {
return YES;
} else if ([name hasPrefix:@"standard"]) {
return YES;
} else if ([name hasPrefix:@"default"]) {
return YES;
} else if ([name hasPrefix:@"main"]) {
return YES;
} // feel free to add any additional prefixes here that I may have neglected
}
}
@finally {
free(methods);
}
return NO;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray *singletons = [NSMutableArray new];
int classCount = objc_getClassList(NULL, 0);
Class *classes = (Class *)malloc(classCount * sizeof(Class));
@try {
classCount = objc_getClassList(classes, classCount);
for (int i = 0; i < classCount; i++) {
Class eachClass = classes[i];
if (ClassIsSingleton(eachClass)) {
[singletons addObject:NSStringFromClass(eachClass)];
}
}
}
@finally {
free(classes);
}
NSLog(@"Singletons: %@", singletons);
}
return 0;
}
source to share