检查对象是否为类类型

时间:2011-06-30 14:20:02

标签: objective-c c type-conversion

我有一个接收NSArray ClassClass个对象的方法,我需要检查它们是否都是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

问题是 for (int i; i<[arr count]; i++) { Class obj = [arr objectAtIndex:i]; if([obj isKindOfClass: [Class class]]) { //do sth } } 不是一个客观的c类,它是一个结构,所以我不能只使用

obj

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

如果答案还提供了检查数组中的项是否为NSPredicate的方法,那将是一个加号,因为示例代码中的项目true也是{{} 1}}用于NSObject检查

6 个答案:

答案 0 :(得分:46)

要确定“对象”是一个类还是一个实例,您需要在两个阶段的过程中检查它是否为meta class。首先调用object_getClass然后使用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];

输出:

  

分类:NSObject
  分类:NSValue
  分类:NSNumber
  分类:NSPredicate
  实例:不是类对象

答案 1 :(得分:8)

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

object_isClass(obj)

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

答案 2 :(得分:5)

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

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

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

根据问题中的输入,结果与Joe的结果相同:

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);
    }
}
  

分类:NSObject
  分类:NSValue
  分类:NSNumber
  分类:NSPredicate
  实例:不是类对象

答案 3 :(得分:1)

如果您需要验证数组中的对象是否是Class对象,那么您可以验证它是否响应类方法。

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

一旦您知道它是Class对象,通过验证它是否响应isSubclassOfClass:,那么您可以检查与[NSObject class]的直接相等。

答案 4 :(得分:-2)

细节即将来临。

首先,在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.

其次,正如您所提到的,&#34; Class不是objective-c class,它是一个结构&#34;。我想解释一下,实际上C中的所有objective-c class都是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类型。

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

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

答案 5 :(得分:-4)

这里没有问题:

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

修改

或者您可以使您的班级符合协议: 并检查从数组中获取的obj是否符合此协议:

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

修改

或者您可以检查从阵列中获得的是否是NSObject complient

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