-
先来看看熟悉的NSObject是个啥吧
@interface NSObject <NSObject> { Class isa OBJC_ISA_AVAILABILITY; }
-
Class是个啥
typedef struct objc_class *Class;
-
objc_class是什么呢
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;
宏判断之间的字段就不一一解释了,网上一搜一大堆。
从这里我们知道,Class是一个结构体,里面保存了类相关的信息。objc_class中本身也有一个Class的字段,即meta-class,指向的还是一个class。于是,网上的有了这样一张图:

简单的说:
当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类的方法列表里查找
当我们发送一个消息给一个类时,这条消息会在类的Meta Class的方法列表里查找
好,以上在网上均可以查到更加详细的资料。下面我们来做道题。
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
这道题本意应该是考察对Class、MetaClass的理解,其实我觉着他更像是考isKindOfClass、isMemberOfClass的实现,挖了好大一个坑的说。
先看一下class的实现吧:
+ (Class)class {
return self;
}
即返回NSObject。
现在我们分析一下res1。看上去应该是这样的:NSObject isKindOfClass NSObject,显然res1 = YES。
(这有何难!!!)
如果你是这样理解的,那么恭喜你,掉坑里了。。。。
我们再看下isKindOfClass的实现
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
和object_getClass的实现
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
isKindOfClass先获取receiver的isa,然后再与参数进行比较。
正确的思考应该是这样的:
1.取得NSObject的isa,既meta_NSObject(我自己瞎编的名字),这个时候meta_NSObject != NSObject
2.根据源码,接下来取meta_NSObject的superClass,根据上一期的类图,即NSObject,这下NSObject == NSObject了。
3.return YES;
剩下的res2、res3同理分析一下~~~~
均为NO。
附录:
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}