我有一个接收NSArray
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"];
类型生成的代码如下:
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
检查
答案 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
,这三种方法。我们可以知道aClass
是Class
类型。这进一步说明了所有objective-c类都是Class
类型。
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
这几乎是我第一次用我糟糕的英语回答问题。如果您还有任何疑问,请尽快回复,我会尽力解释。我还建议您阅读NSObject.h
,runtime.h
,objc.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
}