这是我写的一个小测试程序:
#import <Foundation/Foundation.h>
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *arr = [NSArray array];
printf("Arr isMemberOfClass NSArray: %d\n", [arr isMemberOfClass:[NSArray class]]);
printf("Arr isKindOfClass NSArray: %d\n", [arr isKindOfClass:[NSArray class]]);
[pool release];
return 0;
}
及其输出:
$ ./ismemberof
Arr isMemberOfClass NSArray: 0
Arr isKindOfClass NSArray: 1
任何Foundation类中的-isMemberOfClass:
方法有用吗?我理解这可能会为我子类的类提供所需的结果,但对于基础类 - 我发现我的arr变量的结果是非直观的。之所以会发生这种情况是因为NSArray不是一个具体的类而是一个抽象类,并且在引擎盖下NSArray实际上是NSCFArray的具体实例吗?
答案 0 :(得分:26)
您通常需要isKindOfClass:
,而不是isMemberOfClass:
。不同之处在于,如果接收者是相关类的子类的成员,isKindOfClass:
将返回YES
,而isMemberOfClass:
将在同一情况下返回NO
。 / p>
正如格雷厄姆·李指出的,NSArray
是一个类群。这意味着每个NSArray
实例实际上都是某个子类的实例 - 因此您的发现。只有isKindOfClass:
对于使用类集群进行类成员测试非常有用。
那就是说,你通常应该使用respondsToSelector:
而不是类成员测试。一个示例是objectEnumerator
,它也由NSSet
和NSDictionary
实现(两者也是类集群)。一个例外是plist序列化:集合不是属性列表,因此在尝试从中生成plist数据之前,您需要将allObjects
发送到您的集合以获取数组。
答案 1 :(得分:17)
-isMemberOfClass:在您自己的类中实现-isEqual:方法时非常有用。如果您有这样的课程:
@interface Person : NSObject {
NSString *name;
NSUInteger age;
}
@property(copy) NSString *name;
@property(assign) NSUInteger age;
@end
如果两个Person对象具有相同的名称和年龄,则需要将它们视为相同,您必须实现-isEqual:和NSObject中的-hash方法:protocol:
- (BOOL)isEqual:(id)obj {
return [obj isMemberOfClass:[self class]]
&& [obj name] == self.name
&& [obj age] == self.age;
}
- (NSUInteger)hash {
return [self.name hash] + age;
}
PS:为什么要使用[obj isMemberOfClass:[self class]]
而不是简单[obj class] == [self class]
?它在上面的代码中并不重要,但是当你处理使用NSProxy的更复杂的代码时它变得很重要。如果它是该类的成员,则isMemberOfClass:方法将询问代理所代表的对象,这可能是您想要的。
答案 2 :(得分:2)
我从未使用-isMemberOfClass:我自己,因为如果我已经为现有类添加了功能,通常是通过添加方法,所以-respondsToSelector:给了我我需要的东西。另一方面,我可以看到如何知道您正在查看哪个特定类(一个实例)可能有用。例如,如果您正在处理NSConstantString或NSSimpleCString,那么您可能更愿意对-fastestEncoding进行假设,而不是对其他类的实例进行假设。
要回答身体中的问题,是的,你是对的。 NSArray实现为类集群,因此您将看不到isMemberOfClass: [NSArray class]
的对象。这不会使-isMemberOfClass:毫无意义,只是意味着NSArray永远不会这样。