代码之家  ›  专栏  ›  技术社区  ›  bendytree

如何判断类是否继承自NSObject(Objective-C)

  •  3
  • bendytree  · 技术社区  · 15 年前

    我在iPhone上的Objective-C中工作,需要知道一个“类”是否继承自“NSObject”。

    我试着检查它是否响应NSObject选择器:

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

    但你可以猜到发生了什么。。。它甚至没有响应“respondsToSelector:”所以它抛出了一个“doesNotRecognizeSelector:”异常。

    我试着抓住那个例外,但似乎用“try-”抓住它是不可能的。

    有什么想法吗?

    4 回复  |  直到 15 年前
        1
  •  7
  •   Tommy    15 年前

    直接转到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_对象中唯一确定的东西。

    编辑:另外,iPhone模拟器中还有一些已知的错误,这些错误导致一些异常不能被try/catch块捕获。我已经将它们作为一个bug报告给苹果,并被告知我的是一个副本,所以他们肯定知道。你是在真正的设备上还是在模拟器上试过你的代码?

    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
    }
    
        2
  •  4
  •   Jasarien    15 年前

    你可以用这些方法 isKindOfClass: isMemberOfClass: 确定一个类是另一个类的子类还是一个特定的类。

        3
  •  1
  •   grahamparks    15 年前

    respondsToSelector: 本身是NSObject定义的选择器,因此不能使用它。我不相信没有办法不深入了解Objective-C的内部。

    我可以问一下,为什么您的对象不是NSObject的后代?苹果强烈建议你不要试图去创造它们,而且要有充分的理由。

        4
  •  -3
  •   David Liu    15 年前

    类“class”不是从NSObject继承的。这意味着NSObject定义的方法(例如 isKindOfClass respondsToSelector )不能用在上面。

    你一开始想用它做什么?