3

In an iOS app I am writing I want to traverse a class hierarchy to make an inventory of all subclasses. My intent is to use each subclass type as a key -- via NSStringForClass() -- in a dictionary.

My motivation is to be able to automatically discover all variants of a base class so that I can call methods associated with that class. For reasons of division of labor I prefer not to use method overriding here.

Is it possible to do such a traversal? How would it work?

jscs
  • 63,694
  • 13
  • 151
  • 195
dugla
  • 12,774
  • 26
  • 88
  • 136
  • You may find this question and its answers useful: http://stackoverflow.com/questions/1810628/discover-subclasses-of-a-given-class-in-obj-c – Randolpho Mar 06 '12 at 16:37
  • 1
    This seems bad design to me. If you need to instantiate a different class based on some condition, I think it would be best to use a factory pattern. – JeremyP Mar 06 '12 at 16:54
  • @JeremyP not necessarily; if you've got some sort of setup where you want to register subclasses with a Factory Instantiator, automatic discovery of subclasses could really ease the "i have to manually register every subclass" boilerplate. – Dave DeLong Mar 06 '12 at 18:09
  • @JeremyP. Maybe I wasn't clear, I am not instantiating subclasses here. Rather I am discovering the set of subclasses in the system so that I can associate actions unique to each. Typically this would be automatic via method overriding or protocol conformance on a per class basis. In my case that would force the classes to have "feature envy" which I don't want. The approach I am aiming for is to use a dictionary of class types to identify and guide the functionality I need for a given task. – dugla Mar 06 '12 at 18:56

1 Answers1

7

Here's an example. This method will return all subclasses descending from the class you send the message to.

@interface NSObject (Debugging)

+ (NSArray *) allSubclasses;

@end

@implementation NSObject (Debugging)

+ (NSArray *) allSubclasses
{
    Class myClass = [self class];
    NSMutableArray *mySubclasses = [NSMutableArray array];

    unsigned int numOfClasses;
    Class *classes = objc_copyClassList(&numOfClasses);
    for (unsigned int ci = 0; ci < numOfClasses; ci++) {
        // Replace the code in this loop to limit the result to immediate subclasses:
        // Class superClass = class_getSuperclass(classes[ci]);
        // if (superClass == myClass)
        //  [mySubclasses addObject: classes[ci]];
        Class superClass = classes[ci];
        do {
            superClass = class_getSuperclass(superClass);
        } while (superClass && superClass != myClass);

        if (superClass)
            [mySubclasses addObject: classes[ci]];
    }
    free(classes);

    return mySubclasses;
}

@end

Modify it as needed, make recursive calls, etc.

Costique
  • 23,712
  • 4
  • 76
  • 79