iOS:如何判断id类型的对象是类还是协议

时间:2015-04-03 13:05:47

标签: ios objective-c runtime

这是非常先进的东西。我把一些运行时代码作为一个副项目来搞乱。我试图解决的问题是:如果我有一个id类型的对象,并且该对象可以是字符串或类或协议,我该如何判断它是什么?

例如,这里有一些我正在搞乱的代码:

[objArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[NSString class]]) {
        // Do something with the string ...
    } else if (... obj is a Protocol ...) {
        // Do something with the protocol ...
    } else if (... obj is a Class ...) {
        // Do something with the class ...
    } else {
        // It's something we are not interested in!
    }
}];

到目前为止,我在数组中存储各种NSString,Class和Protocol实例时没有任何问题,其他一切都很好。我需要检测它们的原因很简单,我无法控制进入此代码的内容。所以我需要确定循环处理obj之前的内容是什么。

我一直在尝试各种运行时功能和东西,但到目前为止,如果确定对象是什么,那就没有运气了。

有人试过这样的事吗?

2 个答案:

答案 0 :(得分:2)

我现在可能已经找到了解决方案。

测试id是否为Class:

NSLog(@"isClass %s", object_isClass(obj) ? "yes":"no");

测试id是否为协议:

NSLog(@"isProtocol %s", object_getClass(obj) == objc_getClass("Protocol") ? "yes":"NO");

这些似乎有效,但我认为可能有更好的方法来进行协议检查。

答案 1 :(得分:2)

因为协议 NSObject 的子类,所以您可以像检测其他任何类一样检测它。有趣的是协议类没有公共接口。

id 类型的对象是类或类的实例,所以我先测试它是否为Class,如果失败,则它是一个实例一个类及其使用字符串比较来确定类名。对于协议与@"协议"

进行比较

实施例 -

// assign the object to inspect
id obj = //...
NSString *className;
// test for Class type first
if (object_isClass(obj)) {
// it's a Class... inspect further...
className = NSStringFromClass(obj);
if ([className isEqualToString:@"Protocol"]) { /* Protocol Class */ }
}
else {
// must be an instance - get the class name
className = NSStringFromClass([obj class]);

// test for instance of Protocol class
if ([className isEqualToString:@"Protocol"]) { /* Protocol instance */ }

// continue testing for any other classes here...

}

NSStringFromClass位于Foundation Functions Reference