This worked well (after a little tweaking!) thanks - got the whole caboodle running now. I note that NSObject's superclass is NULL, so I had to switch the order of the while() test in order to correctly detect plain NSObjects (admittedly this will probably never be needed in practice).

Here's my implementation (including objective C 2.0 variant), for anyone's further use:

@implementation MyRuntimeHelper


+ (NSArray*)    allClassesOfKind:(Class) aClass
{
// returns a list of all Class objects that return YES to isKindOfClass:<aClass> currently registered in the runtime
        
        NSMutableArray* list = [NSMutableArray array];

        Class*                  buffer = NULL;
        Class                   cl;
        
        int i, numClasses = objc_getClassList( NULL, 0 );
        
        if( numClasses > 0 )
        {
                buffer = malloc( sizeof(Class) * numClasses );
                
                NSAssert( buffer != nil, @"couldn't allocate the buffer");
                
                (void)  objc_getClassList( buffer, numClasses );
                
                for( i = 0; i < numClasses; ++i )
                {
                        cl = buffer[i];
                        
                        if( classIsSubclassOfClass( cl, aClass ))
                                [list addObject:cl];
                }
                
                free( buffer );
        }
        
        //NSLog(@"classes: %@", list);

        return list;
}

@end



BOOL    classIsNSObject( const Class aClass )
{
// returns YES if <aClass> is an NSObject derivative, otherwise NO. It does this without invoking any methods on the class being tested.
        
        return classIsSubclassOfClass( aClass, [NSObject class]);
}


BOOL    classIsSubclassOfClass( const Class aClass, const Class subclass )
{
        Class   temp = aClass;
        int     match = -1;

#ifndef __OBJC2__
while(( 0 != ( match = strncmp( temp->name, subclass->name, strlen( subclass->name )))) && ( NULL != temp->super_class ))
                temp = temp->super_class;
#else
while(( 0 != ( match = strncmp( class_getName( temp ), class_getName( subclass ), strlen( class_getName( subclass ))))) && ( NULL != class_getSuperclass( temp )))
                temp = class_getSuperclass( temp );
#endif
        return ( match == 0 );
}



On 27 Mar 2008, at 4:11 pm, Sherm Pendley wrote:
On Thu, Mar 27, 2008 at 12:43 AM, Graham Cox <[EMAIL PROTECTED]> wrote:

I have a class that can contain different objects which all derive
from a class R. The container can accept instances of any subclass of R.

Each subclass of R implements a CLASS method for a particular feature,
returning an array. The container needs to build an array which is the
union of all the arrays returned by each subclass. Thus it needs to
iterate through a list of all possible subclasses of R, combining the
arrays as it goes. Problem is that not all possible subclasses of R
are known until runtime, so I need a way to be able to get hold of
such a list, based on the fact that they all inherit from R. Note that
these are not instances of R, but classes. (I can get a list of
instances I have right now, but that doesn't cover the possibility of
another object instance derived from R being added after I already
built the array).

Hope this makes sense - any ideas?

You're on the right track, IMHO. What I would do is climb the inheritance tree for each registered class. If you find an ancestor with the name of R, the class you're checking is a subclass. If you get to a root class (i.e. a class whose super_class member is NULL), then it's not.

while( NULL != aClass->super_class && 0 != strncmp(aClass->name, "R", 1) )
    aClass = aClass->super_class;

BOOL isSubclassOfR = (NULL != aClass->super_class) ? YES : NO;

Keep in mind that this is for the ObjC 1 runtime. I haven't yet looked at the ObjC 2 runtime in any detail, so if you're targeting 64-bit Leopard, YMMV.

sherm--


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to