How to tell if a Class inherits from NSObject (Objective-C)

iphone, nsobject, objective-c, reflection

Solution

Go direct to the Objective-C runtime:

#import <objc/runtime.h>

/* originally posted version — works because eventually class_getSuperclass(class)
returns nil, and class_getSuperclass(nil) does so also. */
BOOL classDescendsFromClass(Class classA, Class classB)
{
    while(1)
    {
        if(classA == classB) return YES;
        id superClass = class_getSuperclass(classA);
        if(classA == superClass) return (superClass == classB);
        classA = superClass;
    }
}

/* shorter version; exits straight after classA turns into nil */
BOOL classDescendsFromClassShorter(Class classA, Class classB)
{
    while(classA)
    {
        if(classA == classB) return YES;
        classA = class_getSuperclass(classA);
    }

    return NO;
}
...

if(classDescendsFromClass(classToTest->isa, [NSObject class]) ...

`class_getSuperclass` does what it says, and it's safe to compare metaclasses by pointer in the Objective-C runtime because there is only exactly one instance of the metaclass for each class. The isa pointer is the only thing that's definitely in struct objc_object.

EDIT: additionally, there are known bugs in the iPhone simulator that cause some exceptions not to be caught by try/catch blocks. I've reported them as a bug to Apple and been told that mine was a duplicate, so they are definitely aware. Did you try your code on a real device or just in the simulator?

EDIT2: from the wider context given elsewhere in this conversation, something like this might be smarter:

#import <objc/runtime.h>

BOOL classRespondsToSelector(Class classA, SEL selector)
{
    return class_getInstanceMethod(classA, selector) ? YES : NO;
}

....
if(classRespondsToSelector(instance->isa, @selector(respondsToSelector:))
{
     // great, we've got something that responds to respondsToSelector:; do the
     // rest of our querying through there
}

Problem

I'm working in Objective-C on the iPhone and need to know whether a 'Class' inherits from 'NSObject'. I tried checking if it responds to an NSObject selector: ``` bool success = [myClass respondsToSelector:@selector(class)]; ``` but you can guess what happened... it didn't even respond to "respondsToSelector:" so it throws a "does not implement doesNotRecognizeSelector:" exception. I tried to catch that exception, but it looks like it can't be caught with a @try-@catch. Any ideas?

Original source