Как определить, наследуется ли класс от NSObject (Objective-C) - PullRequest
3 голосов
/ 23 ноября 2010

Я работаю в Objective-C на iPhone, и мне нужно знать, наследуется ли «класс» от «NSObject».

Я попытался проверить, отвечает ли он на селектор NSObject:

bool success = [myClass respondsToSelector:@selector(class)];

но вы можете догадаться, что случилось ... он даже не ответил на "responsedsToSelector:", поэтому он выбрасывает "не реализует исключение" doNotRecognizeSelector: "., но, похоже, его нельзя поймать с помощью @ try- @ catch.

Есть идеи?

Ответы [ 4 ]

7 голосов
/ 23 ноября 2010

Перейти непосредственно к среде выполнения Objective C:

#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 делает то, что говорит, и можно безопасно сравнивать метаклассы по указателю во время выполнения Objective C, поскольку для каждого класса существует только один экземпляр метакласса. Указатель isa - это единственное, что определенно есть в структуре objc_object.

РЕДАКТИРОВАТЬ: кроме того, в симуляторе iPhone есть известные ошибки, которые приводят к тому, что некоторые исключения не блокируются блоками try / catch. Я сообщил о них как об ошибке в Apple, и мне сказали, что у меня был дубликат, поэтому они определенно знают. Вы пробовали свой код на реальном устройстве или просто в симуляторе?

EDIT2: из более широкого контекста, приведенного в другом месте этого разговора, что-то вроде этого может быть умнее:

#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
}
4 голосов
/ 23 ноября 2010

Вы можете использовать методы isKindOfClass: и isMemberOfClass:, чтобы определить, является ли класс подклассом другого класса или это определенный класс.

1 голос
/ 23 ноября 2010

respondsToSelector: сам по себе является селектором, определяемым NSObject, поэтому его нельзя использовать. Я не верю, что есть способ сделать это, не углубившись во внутренности Objective-C.

Могу я спросить, почему у вас есть объекты, которые не являются потомками NSObject? Apple настоятельно рекомендует вам не пытаться их создавать, и для этого есть все основания.

0 голосов
/ 23 ноября 2010

Класс 'Class' не наследуется от NSObject.Это означает, что методы, определенные NSObject (например, isKindOfClass или respondsToSelector), не могут быть использованы на нем.

Что вы пытаетесь сделать с ним в первую очередь?

...