美文网首页
Runtime-isMemberOfClass

Runtime-isMemberOfClass

作者: 刘刘浩 | 来源:发表于2020-06-12 00:46 被阅读0次

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的值,正好是类对象的地址

相关文章

  • Runtime-isMemberOfClass

    isMemberOfClass用来判断对象是否是某个类的实例 由上一篇类与对象的关系可以知道: Class类型即为...

网友评论

      本文标题:Runtime-isMemberOfClass

      本文链接:https://www.haomeiwen.com/subject/jpzmtktx.html