如何使用Class来确定它是否继承自另一个类?

时间:2014-03-07 18:54:54

标签: ios objective-c ios7

我只有一个Class字符串的映射,用于确定字符串表示的Class是否继承自另一个Class。我知道我可以在对象的实例上使用isKindOfClass,但我不知道如何使用Class。所以我想做点像......

NSString *className = [self.classMapping objectForKey:key];
Class class = NSClassFromString(className);
if (/* class inherits from ClassA */) 
    ClassA *classA = [[ClassA alloc] initWithClassAInitializer];
else if (/* class inherits from ClassB */)
    ClassB *classB = [[ClassB alloc] initWithClassBInitializer];

...但我不知道if语句中有什么内容。如何使用Class来确定它是否继承自另一个类?

提前感谢您的智慧!

3 个答案:

答案 0 :(得分:0)

这些检查是不必要的,您只需在类本身上调用alloc即可获得所需的初始化。

Class class = NSClassFromString(className)

id object = [[class alloc] init];
这里的

id可以替换为所有这些类继承的根类。如果可能,您的子类应该都使用通用的init方法,在自己的init中为超级init提供任何附加功能。这样可以避免进行这些检查。

答案 1 :(得分:0)

正如评论中所指出的,您可以在类对象上使用NSObject继承方法。您还可以直接比较类对象的相等性:

Class c = NSClassFromString(className);
if( c == [ClassA class] ){
    /* create instance of ClassA */
}
else if ...

答案 2 :(得分:0)

最简单的方法:Class是一个对象,所以你可以这样做:

NSLog(@"%d", [[@"Test" class] isSubclassOfClass:[NSString class]]);
NSLog(@"%d", [[@"Test" class] isSubclassOfClass:[NSObject class]]);
NSLog(@"%d", [[@"Test" class] isSubclassOfClass:[NSArray class]]);

您也可以使用低级Objective-C运行时函数来解决这个问题:

#import <objc/runtime.h>

BOOL isClassSubclassOf(Class classToTest, Class maybeParentClass)
{
    do {
        if (classToTest == maybeParentClass) {
            return YES;
        }

        classToTest = class_getSuperclass(classToTest);
    } while (classToTest != NULL);

    return NO;
}

int main(int argc, char *argv[]){
    @autoreleasepool{
        NSLog(@"%d", isClassSubclassOf([@"Test" class], [NSString class]));
        NSLog(@"%d", isClassSubclassOf([@"Test" class], [NSObject class]));
        NSLog(@"%d", isClassSubclassOf([@"Test" class], [NSArray class]));
    }
}

最后但并非最不重要的是,如果初始化程序名称不同/唯一,您也可以使用ducktyping:

Class klass;
id obj = nil;

klass = [NSString class];
// klass = [NSArray class];

if (class_getInstanceMethod(klass, @selector(initWithFormat:))) {
    obj = [[klass alloc] initWithFormat:@"It's string-like!"];
} else if (class_getInstanceMethod(klass, @selector(initWithObjects:))) {
    obj = [[klass alloc] initWithObjects:@"It's", @"array-like", nil];
}

NSLog(@"%@", obj);

按原样,您将收到日志消息It's string-like!,但如果您取消注释注释行,则会获得( "It's", "array-like" )