I'm working in Objective-C on the iPhone and need to know whether a 'Class' inherits from 'NSObject'.
我在iPhone上使用Objective-C,需要知道一个类是否继承自NSObject。
I tried checking if it responds to an NSObject selector:
我试着检查它是否响应NSObject选择器:
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.
但是你可以猜到发生了什么……它甚至没有响应"respondsToSelector:"因此它抛出"does notrecognizeselector:" exception "。
I tried to catch that exception, but it looks like it can't be caught with a @try-@catch.
我试图捕获这个异常,但是看起来它不能被@try-@catch捕获。
Any ideas?
什么好主意吗?
4 个解决方案
#1
7
Go direct to the Objective-C runtime:
直接到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
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.
class_getSuperclass实现了它所说的,在Objective-C运行时通过指针比较元类是安全的,因为每个类只有一个元类实例。isa指针是唯一明确存在于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?
编辑:此外,iPhone模拟器中有一些已知的bug,导致一些异常不会被try/catch块捕获。我曾向苹果报告过它们是一个bug,并被告知我的是一个副本,所以他们肯定知道。你试过你的代码在一个真实的设备上还是仅仅在模拟器上?
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
}
#2
4
You can use the methods isKindOfClass:
and isMemberOfClass:
to determine whether a class is a subclass of another class or if it is a particular class.
您可以使用isKindOfClass:和isMemberOfClass:方法来确定一个类是另一个类的子类,还是它是一个特定的类。
#3
1
respondsToSelector:
is itself an NSObject-defined selector, so you can't use it. I don't believe there's a way to do this without getting very deep into the internals of Objective-C.
respondsToSelector:本身就是一个nsobject定义的选择器,所以你不能使用它。我不相信有一种方法可以不深入到Objective-C的内部。
May I ask why you have objects that aren't descendants of NSObject? Apple very strongly recommends you don't attempt to create them, and with good reason.
我可以问一下,为什么你的对象不是NSObject的后代?苹果强烈建议你不要尝试去创造它们,而且要有充分的理由。
#4
-3
The class 'Class' does not inherit from NSObject. That means methods defined by NSObject (such as isKindOfClass
or respondsToSelector
) cannot be used on it.
类“类”不从NSObject继承。这意味着NSObject(如isKindOfClass或respondsToSelector)定义的方法不能在其上使用。
What are you trying to do with it in the first place?
首先,你想用它做什么?
#1
7
Go direct to the Objective-C runtime:
直接到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
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.
class_getSuperclass实现了它所说的,在Objective-C运行时通过指针比较元类是安全的,因为每个类只有一个元类实例。isa指针是唯一明确存在于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?
编辑:此外,iPhone模拟器中有一些已知的bug,导致一些异常不会被try/catch块捕获。我曾向苹果报告过它们是一个bug,并被告知我的是一个副本,所以他们肯定知道。你试过你的代码在一个真实的设备上还是仅仅在模拟器上?
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
}
#2
4
You can use the methods isKindOfClass:
and isMemberOfClass:
to determine whether a class is a subclass of another class or if it is a particular class.
您可以使用isKindOfClass:和isMemberOfClass:方法来确定一个类是另一个类的子类,还是它是一个特定的类。
#3
1
respondsToSelector:
is itself an NSObject-defined selector, so you can't use it. I don't believe there's a way to do this without getting very deep into the internals of Objective-C.
respondsToSelector:本身就是一个nsobject定义的选择器,所以你不能使用它。我不相信有一种方法可以不深入到Objective-C的内部。
May I ask why you have objects that aren't descendants of NSObject? Apple very strongly recommends you don't attempt to create them, and with good reason.
我可以问一下,为什么你的对象不是NSObject的后代?苹果强烈建议你不要尝试去创造它们,而且要有充分的理由。
#4
-3
The class 'Class' does not inherit from NSObject. That means methods defined by NSObject (such as isKindOfClass
or respondsToSelector
) cannot be used on it.
类“类”不从NSObject继承。这意味着NSObject(如isKindOfClass或respondsToSelector)定义的方法不能在其上使用。
What are you trying to do with it in the first place?
首先,你想用它做什么?