- [NSObject isMemberOfClass:]方法有用吗?

时间:2008-12-21 01:28:11

标签: objective-c cocoa

这是我写的一个小测试程序:

#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的具体实例吗?

3 个答案:

答案 0 :(得分:26)

您通常需要isKindOfClass:,而不是isMemberOfClass:。不同之处在于,如果接收者是相关类的子类的成员,isKindOfClass:将返回YES,而isMemberOfClass:将在同一情况下返回NO。 / p>

正如格雷厄姆·李指出的,NSArray是一个类群。这意味着每个NSArray实例实际上都是某个子类的实例 - 因此您的发现。只有isKindOfClass:对于使用类集群进行类成员测试非常有用。

那就是说,你通常应该使用respondsToSelector:而不是类成员测试。一个示例是objectEnumerator,它也由NSSetNSDictionary实现(两者也是类集群)。一个例外是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永远不会这样。