繁体   English   中英

检查 object 是否为 Class 类型

[英]Check if object is Class type

我有一个接收Class对象的NSArray的方法,我需要检查它们是否都是使用以下代码生成的Class类型:

NSMutableArray *arr = [[NSMutableArray alloc] init];

[arr addObject:[NSObject class]];
[arr addObject:[NSValue class]];
[arr addObject:[NSNumber class]];
[arr addObject:[NSPredicate class]];
[arr addObject:@"not a class object"];

问题是Class不是 objective-c class,它是一个结构,所以我不能只使用

    for (int i; i<[arr count]; i++) {
        Class obj = [arr objectAtIndex:i];

        if([obj isKindOfClass: [Class class]]) {
            //do sth
        }
    }

所以,我需要检查obj变量是否是Class类型,我想它会直接在C中,但我该怎么做呢?

如果答案还提供了一种检查数组中的项目是否为NSObject的方法,那将是一个加号,因为示例代码中的项目, NSPredicatetrueNSObject检查

要确定“对象”是 class 还是实例,您需要在两阶段过程中检查它是否是元 class 首先调用object_getClass然后使用 class_isMetaClass 检查它是否是元class_isMetaClass 您将需要#import <objc/runtime.h>

NSObject *object = [[NSObject alloc] init];
Class class = [NSObject class];

BOOL yup = class_isMetaClass(object_getClass(class));
BOOL nope = class_isMetaClass(object_getClass(object));

Class*id都具有相同的结构布局( Class isa ),因此可以作为对象并且都可以接收消息,因此很难确定哪个是哪个。 这似乎是我能够获得一致结果的唯一方法。

编辑:

这是您的原始支票示例:

NSMutableArray *arr = [[NSMutableArray alloc] init];

[arr addObject:[NSObject class]];
[arr addObject:[NSValue class]];
[arr addObject:[NSNumber class]];
[arr addObject:[NSPredicate class]];
[arr addObject:@"not a class object"];

for (int i; i<[arr count]; i++) {
    id obj = [arr objectAtIndex:i];

    if(class_isMetaClass(object_getClass(obj)))
    {
        //do sth
        NSLog(@"Class: %@", obj);
    }
    else
    {
        NSLog(@"Instance: %@", obj);
    }
}

[arr release];

和 output:

Class:NSObject
Class:NSValue
Class:NSNumber
Class:NSPredicate
实例:不是 class object

更新:在 iOS 8+ 或 OS X 10.10+ 中,您可以这样做:

object_isClass(obj)

(您需要#import <objc/runtime.h> 。)

乔的回答很好。 在大多数情况下有效的一个简单替代方法是检查 object 是否返回自身以响应class

if ([obj class] == obj) { … }

这是因为NSObject元类覆盖class并返回 class object (本身) - 请参阅NSObject Z9BD781329FEDBEBF6AFE23 这不需要运行时标头,但假定对象是NSObject的子类,并且不覆盖-class+class并做一些不寻常的事情。


使用问题中的输入,结果与乔的相同:

NSMutableArray *arr = [[NSMutableArray alloc] init];

[arr addObject:[NSObject class]];
[arr addObject:[NSValue class]];
[arr addObject:[NSNumber class]];
[arr addObject:[NSPredicate class]];
[arr addObject:@"not a class object"];

for (id<NSObject> obj in arr) {

    if ([obj class] == obj) {
        NSLog(@"Class: %@", obj);
    }
    else {
        NSLog(@"Instance: %@", obj);
    }
}

Class:NSObject
Class:NSValue
Class:NSNumber
Class:NSPredicate
实例:不是 class object

如果需要验证数组中的 object 是否为Class object 则可以验证它是否响应 ZA2F2ED4F8EBC2CBB4DZ21A2 方法。

for ( id obj in arr ) {
    if (([obj respondsToSelector:@selector(isSubclassOfClass:)])
          && (obj == [NSObject class]) ) {
        NSLog(@"%@", obj);
    }
}

一旦你知道它是一个Class object 通过验证它是否响应isSubclassOfClass:然后你可以检查与[NSObject class]的直接相等性。

细节来了。

首先,在objc.h中,我们可以找到这些代码:

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

这意味着所有Objective-C class都是Class类型,包括NSObject

所以你的问题:

[arr addObject:[NSObject class]]; /// YES
[arr addObject:[NSValue class]];  /// YES
[arr addObject:[NSNumber class]];   /// YES
[arr addObject:[NSPredicate class]];   /// YES
[arr addObject:@"not a class object"];   /// NO, It's just a NSString.

其次,正如您所提到的,“ Class不是objective-c class ,它是一个结构”。 我想解释一下objective-c class class 实际上是 C 中的Struct

runtime.h中,我找到了这些代码,也许对我们有帮助:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

最后我们来看看NSObject.h line30--32 ,这三个方法。 我们可以知道aClassClass类型。 这进一步说明所有 objective-c class 都是Class类型。

- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

这几乎是我第一次用我蹩脚的英语回答问题。 如果您还有任何问题,请尽快回复,我会尽力解释。 而且我还建议你阅读NSObject.hruntime.hobjc.h代码,也许它会对你有所帮助。

这里没有问题是你如何做到的:

if([NSStringFromClass([obj class]) isEqualToString:@"Class"]){
    NSLog(@"It is type of Class");
}

编辑

或者您可以使您的 Class 符合协议:并检查您从数组中获得的 obj 是否符合此协议,如下所示:

if([obj conformsToProtocol:@protocol(MyClassProtocol)])

编辑

或者您可以检查从数组中获得的内容是否符合 NSObject

if ([object conformsToProtocol:@protocol(NSObject)]) {
    // Do something
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM