isMemberOfClass用来判断对象是否是某个类的实例
Class cls = [Person class];
BOOL isSame = [person isMemberOfClass:cls];
由上一篇类与对象的关系可以知道:
- Class类型即为objc_class *指针类型
- 实例对象的isa指针指向类对象
可以推测cls即为指向类对象的指针,而isMemberOfClass通过对比实例对象的isa指针和cls指针来进行判断
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
实例对象调用class方法,内部调用了runtime的object_getClass方法
- (Class)class {
return object_getClass(self);
}
对象的结构体是objc_object,因此可以调用结构体定义的getIsa()方法
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
花开两朵,先表一枝,看下!isTaggedPointer()的情况,继续调用ISA()方法
inline Class
objc_object::getIsa()
{
if (!isTaggedPointer()) return ISA();
uintptr_t ptr = (uintptr_t)this;
if (isExtTaggedPointer()) {
uintptr_t slot =
(ptr >> _OBJC_TAG_EXT_SLOT_SHIFT) & _OBJC_TAG_EXT_SLOT_MASK;
return objc_tag_ext_classes[slot];
} else {
uintptr_t slot =
(ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_SLOT_MASK;
return objc_tag_classes[slot];
}
}
同样跳过if,只看else分支,最终返回的是isa.bits & ISA_MASK
inline Class
objc_object::ISA()
{
assert(!isTaggedPointer());
#if SUPPORT_INDEXED_ISA
if (isa.nonpointer) {
uintptr_t slot = isa.indexcls;
return classForIndex((unsigned)slot);
}
return (Class)isa.bits;
#else
return (Class)(isa.bits & ISA_MASK);
#endif
}
由上一篇类与对象的关系分析可知,isa指针中,只有33位用来储存类对象的地址,而ISA_MASK的作用就是获取地址值
使用lldb打印几个变量的二进制值
0b0000000000000000000000000000000100000000000000000001001101000000 cls
0b0000000000011101100000000000000100000000000000000001001101101001 isa.bits
0b0000000000000000011111111111111111111111111111111111111111111000 ISA_MASK
可以看到,isa.bits & ISA_MASK的值,正好是类对象的地址