I have a method that receives a NSArray
of Class
objects and I need to check if they all are Class
type generated with the code bellow:
我有一个接收类对象NSArray的方法,我需要检查它们是否都是用下面的代码生成的类类型:
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"];
The problem is that Class
is not an objective-c class, it is a struc, so I can not use just
问题是类不是objective-c类,而是struc,所以我不能只使用它
for (int i; i<[arr count]; i++) {
Class obj = [arr objectAtIndex:i];
if([obj isKindOfClass: [Class class]]) {
//do sth
}
}
So, I need to I check if the obj
variable is a Class
type, I suppose it will be in C
directly, but how can I do that?
我需要检查obj变量是否是类类型,我想它会在C中,但是我怎么做呢?
It will be a plus if the answer also provide a way to check if the item in the array is a NSObject
, as the items in the example code, the NSPredicate
would also be true
for the NSObject
check
如果答案还提供了一种检查数组中的项是否为NSObject的方法,那么它将是一个加号,就像示例代码中的项一样,NSPredicate对于NSObject检查也是正确的
6 个解决方案
#1
45
To determine if an "object" is a class or an instance you need to check if it is a meta class in a two stage process. First call object_getClass
then check if it is a meta class using class_isMetaClass
. You will need to #import <objc/runtime.h>
.
要确定一个“对象”是一个类还是一个实例,您需要检查它是否是两个阶段过程中的一个元类。首先调用object_getClass,然后使用class_isMetaClass检查它是否是一个元类。您将需要#import
NSObject *object = [[NSObject alloc] init];
Class class = [NSObject class];
BOOL yup = class_isMetaClass(object_getClass(class));
BOOL nope = class_isMetaClass(object_getClass(object));
Both Class
and *id
have the same struct layout (Class isa
), therefore can pose as objects and can both receive messages making it hard to determine which is which. This seems to be the only way I was able to get consistent results.
类和*id都具有相同的结构布局(类isa),因此它们都可以摆成对象,并且都可以接收消息,这使得很难确定哪个是哪个。这似乎是我获得一致结果的唯一途径。
EDIT:
编辑:
Here is your original example with the check:
这是你的原始例子,支票:
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];
And the output:
和输出:
Class: NSObject
Class: NSValue
Class: NSNumber
Class: NSPredicate
Instance: not a class object类:NSObject类:NSValue类:NSNumber类:NSPredicate实例:不是类对象。
#2
8
Update: In iOS 8+ or OS X 10.10+, you can just do:
更新:在iOS 8+或OS X 10.10+中,你只需要:
object_isClass(obj)
(You will need to #import <objc/runtime.h>
.)
(您需要#import
#3
4
Joe’s answer is good. A simple alternative that works in most situations is to check if the object returns itself in response to class
.
乔的回答是好的。在大多数情况下,一个简单的替代方法是检查对象是否返回自己以响应类。
if ([obj class] == obj) { … }
This works because the NSObject
meta-class overrides class
and returns the class object (itself) — see the NSObject Class Reference. This does not require the runtime headers, but assumes the objects are subclasses of NSObject
and don’t override -class
or +class
and do something unusual.
这是因为NSObject元类覆盖类并返回类对象(本身)——请参见NSObject类引用。这并不需要运行时标头,但是假设对象是NSObject的子类,并且不重写-类或+类,并做一些不寻常的事情。
With the input in the question, the results are the same as Joe’s:
有了问题的输入,结果和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);
}
}
Class: NSObject
Class: NSValue
Class: NSNumber
Class: NSPredicate
Instance: not a class object类:NSObject类:NSValue类:NSNumber类:NSPredicate实例:不是类对象。
#4
1
If you need to verify if the object in the array is a Class
object then you can verify if it responds to class methods.
如果需要验证数组中的对象是否是类对象,那么可以验证它是否响应类方法。
for ( id obj in arr ) {
if (([obj respondsToSelector:@selector(isSubclassOfClass:)])
&& (obj == [NSObject class]) ) {
NSLog(@"%@", obj);
}
}
Once you know it is a Class
object by verifying if it responds to isSubclassOfClass:
then you can check for direct equality with [NSObject class]
.
一旦您通过验证它是否响应isSubclassOfClass来知道它是一个类对象:然后您可以检查它与[NSObject类]的直接相等性。
#5
-2
The detail is comming.
细节,请等待。
First, In objc.h
, we can find these codes:
首先,在objc。h,我们可以找到这些代码:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
that means all Objective-C class
is Class
type, including NSObject
.
这意味着所有Objective-C类都是类类型,包括NSObject。
so your question:
所以你的问题:
[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.
Second, As you have mentioned, "Class
is not an objective-c class
, it is a struct". I want to explain that all objective-c class
are Struct
in C actually.
第二,正如您所提到的,“类不是一个objective-c类,而是一个struct”。我想解释所有objective-c类实际上都是C中的Struct。
In runtime.h
, I find these codes, maybe help us:
在运行时。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;
Finally let's come to NSObject.h
line30--32
, these three methods. We can know that aClass
is Class
type. That further illustrates that all objective-c class is Class
type.
最后我们来看看NSObject。h行30- 32,这三种方法。我们可以知道aClass是类类型。这进一步说明了objective-c类都是类类型。
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
It's almost my first time to answer question in my poor English. If you also have any questions, please reply soon, I will try my best to explain it. And I also suggest you to read NSObject.h
, runtime.h
, objc.h
code, maybe it will help you.
这几乎是我第一次用我蹩脚的英语回答问题。如果您还有什么问题,请尽快回复,我会尽力解释的。我也建议你们读NSObject。h,运行时。h,objc。h代码,可能会对你有帮助。
#6
-4
No problem here is how you do it:
这里没有问题是你怎么做的:
if([NSStringFromClass([obj class]) isEqualToString:@"Class"]){
NSLog(@"It is type of Class");
}
Edit
编辑
Or you can make your Class conform to a protocol: and check if obj that you get from the array conforms to this protocol like this:
或者你可以让你的类符合一个协议:检查你从数组中得到的obj是否符合这个协议,比如:
if([obj conformsToProtocol:@protocol(MyClassProtocol)])
Edit
编辑
Or you can check if what you get from the array is an NSObject complient
或者您可以检查从数组中获得的内容是否为NSObject遵从性
if ([object conformsToProtocol:@protocol(NSObject)]) {
// Do something
}
#1
45
To determine if an "object" is a class or an instance you need to check if it is a meta class in a two stage process. First call object_getClass
then check if it is a meta class using class_isMetaClass
. You will need to #import <objc/runtime.h>
.
要确定一个“对象”是一个类还是一个实例,您需要检查它是否是两个阶段过程中的一个元类。首先调用object_getClass,然后使用class_isMetaClass检查它是否是一个元类。您将需要#import
NSObject *object = [[NSObject alloc] init];
Class class = [NSObject class];
BOOL yup = class_isMetaClass(object_getClass(class));
BOOL nope = class_isMetaClass(object_getClass(object));
Both Class
and *id
have the same struct layout (Class isa
), therefore can pose as objects and can both receive messages making it hard to determine which is which. This seems to be the only way I was able to get consistent results.
类和*id都具有相同的结构布局(类isa),因此它们都可以摆成对象,并且都可以接收消息,这使得很难确定哪个是哪个。这似乎是我获得一致结果的唯一途径。
EDIT:
编辑:
Here is your original example with the check:
这是你的原始例子,支票:
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];
And the output:
和输出:
Class: NSObject
Class: NSValue
Class: NSNumber
Class: NSPredicate
Instance: not a class object类:NSObject类:NSValue类:NSNumber类:NSPredicate实例:不是类对象。
#2
8
Update: In iOS 8+ or OS X 10.10+, you can just do:
更新:在iOS 8+或OS X 10.10+中,你只需要:
object_isClass(obj)
(You will need to #import <objc/runtime.h>
.)
(您需要#import
#3
4
Joe’s answer is good. A simple alternative that works in most situations is to check if the object returns itself in response to class
.
乔的回答是好的。在大多数情况下,一个简单的替代方法是检查对象是否返回自己以响应类。
if ([obj class] == obj) { … }
This works because the NSObject
meta-class overrides class
and returns the class object (itself) — see the NSObject Class Reference. This does not require the runtime headers, but assumes the objects are subclasses of NSObject
and don’t override -class
or +class
and do something unusual.
这是因为NSObject元类覆盖类并返回类对象(本身)——请参见NSObject类引用。这并不需要运行时标头,但是假设对象是NSObject的子类,并且不重写-类或+类,并做一些不寻常的事情。
With the input in the question, the results are the same as Joe’s:
有了问题的输入,结果和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);
}
}
Class: NSObject
Class: NSValue
Class: NSNumber
Class: NSPredicate
Instance: not a class object类:NSObject类:NSValue类:NSNumber类:NSPredicate实例:不是类对象。
#4
1
If you need to verify if the object in the array is a Class
object then you can verify if it responds to class methods.
如果需要验证数组中的对象是否是类对象,那么可以验证它是否响应类方法。
for ( id obj in arr ) {
if (([obj respondsToSelector:@selector(isSubclassOfClass:)])
&& (obj == [NSObject class]) ) {
NSLog(@"%@", obj);
}
}
Once you know it is a Class
object by verifying if it responds to isSubclassOfClass:
then you can check for direct equality with [NSObject class]
.
一旦您通过验证它是否响应isSubclassOfClass来知道它是一个类对象:然后您可以检查它与[NSObject类]的直接相等性。
#5
-2
The detail is comming.
细节,请等待。
First, In objc.h
, we can find these codes:
首先,在objc。h,我们可以找到这些代码:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
that means all Objective-C class
is Class
type, including NSObject
.
这意味着所有Objective-C类都是类类型,包括NSObject。
so your question:
所以你的问题:
[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.
Second, As you have mentioned, "Class
is not an objective-c class
, it is a struct". I want to explain that all objective-c class
are Struct
in C actually.
第二,正如您所提到的,“类不是一个objective-c类,而是一个struct”。我想解释所有objective-c类实际上都是C中的Struct。
In runtime.h
, I find these codes, maybe help us:
在运行时。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;
Finally let's come to NSObject.h
line30--32
, these three methods. We can know that aClass
is Class
type. That further illustrates that all objective-c class is Class
type.
最后我们来看看NSObject。h行30- 32,这三种方法。我们可以知道aClass是类类型。这进一步说明了objective-c类都是类类型。
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
It's almost my first time to answer question in my poor English. If you also have any questions, please reply soon, I will try my best to explain it. And I also suggest you to read NSObject.h
, runtime.h
, objc.h
code, maybe it will help you.
这几乎是我第一次用我蹩脚的英语回答问题。如果您还有什么问题,请尽快回复,我会尽力解释的。我也建议你们读NSObject。h,运行时。h,objc。h代码,可能会对你有帮助。
#6
-4
No problem here is how you do it:
这里没有问题是你怎么做的:
if([NSStringFromClass([obj class]) isEqualToString:@"Class"]){
NSLog(@"It is type of Class");
}
Edit
编辑
Or you can make your Class conform to a protocol: and check if obj that you get from the array conforms to this protocol like this:
或者你可以让你的类符合一个协议:检查你从数组中得到的obj是否符合这个协议,比如:
if([obj conformsToProtocol:@protocol(MyClassProtocol)])
Edit
编辑
Or you can check if what you get from the array is an NSObject complient
或者您可以检查从数组中获得的内容是否为NSObject遵从性
if ([object conformsToProtocol:@protocol(NSObject)]) {
// Do something
}