2010-11-22 2 views
3

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

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

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

но вы можете догадаться, что произошло ... он даже не ответил на «respondsToSelector:» так бросает «не реализует doesNotRecognizeSelector: "исключение.

Я попытался поймать это исключение, но похоже, что он не может быть пойман с помощью @ [email protected] catch.

Любые идеи?

+2

Я думаю, лучше спросить, как вы пришли иметь дело с этими классами, которые не наследовать от NSObject. Там не должно быть никаких протоколов. – Chuck 2010-11-22 23:33:16

+1

@Chuck и `NSProxy`. – 2010-11-23 00:52:20

+0

Вы имеете в виду `@selector (class)`. Я не думаю, что в SDK есть что-то, что отвечает на `+ class:`. – 2010-11-23 03:00:25

ответ

7

Перейти сразу к выполнению 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 - это единственное, что определенно в struct objc_object.

EDIT: кроме того, в симуляторе 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

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

1

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

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

-3

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

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