iOS isa指针笔记

isa指针本质

  • 在arm64架构之前isa就是一个普通指针
  • 在arm64架构之后,对isa进行了优化,变成了一个共用体union结构,还用了位域来存储更多的信息
union isa_t
{
    Class cls;
    uintptr_t bits;
    struct {
        uintptr_t nonpointer        :1;
        uintptr_t has_assoc         :1;
        uintptr_t has_cxx_dtor      :1;
        uintptr_t shiftcls          :33;
        uintptr_t magic             :6;
        uintptr_t weakly_referenced :1;
        uintptr_t deallocating      :1;
        uintptr_t has_sidetable_rc  :1;
        uintptr_t extra_rc          :19;
    };
};
  • nonpointer
0,表示普通指针,存储着Class、Meta-Class对象的内存地址
1,代表优化过,使用位域存储更多的信息
  • has_assoc
是否有设置过关联对象,如果没有,释放时会更快
  • has_cxx_dtor
是否有C++的析构函数(.cxx_destruct),如果没有释放时会更快
  • shiftcls
存放着Class、Meta-Class对象的内存地址信息
  • magic
用于在调试的时候分辨对象是否未完成初始化
  • weakly_referenced
是否有被弱引用指向过,如果没有,释放时会更快
  • deallocating
对象是否正在释放
  • has_sidetable_rc
1.引用计数器是否过大无法存储在isa中
2.如果为1,引用计数器会存储在SideTable的类属性中
  • extra_rc
里面存储的值是引用计数器-1

isa的日常使用

isa的指向逻辑

  • 实例对象的isa指向class
  • class的isa指向meta-class
  • meta-class的isa指向基类的meta-class

superclass的指向逻辑

  • class的superclass指向父类的class;如果没有父类,superclass指向nil。(通过superclass找到父类的meta-class,直到找到类方法的实现进行调用)
  • meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类class
isa和superclass的指向逻辑.png

方法调用逻辑

  • 在调用对象方法的时候,通过实例对象的isa找到class,如果方法不存在,就通过superclass找父类,直到找到对象方法进行调用
  • 当调用类方法的时候,通过class的isa找到meta-class,如果方法没知道到,就通过superclass找到父类的meta-class,直到找到类方法的实现进行调用;如果最后基类meta-class也没有找到类方法的实现,就通过superclass找到基类的class,在基类的class中查找同名的对象方法,如果找到了同名的对象方法就进行调用,如果没找到就会进入动态方法解析阶段,动态解析后仍然没有找到方法实现就会进入消息转发阶段,如果都没有处理就抛出NSInvalidArgumentException异常。

isa的内存地址和类对象的内存地址的关系

class的地址值:isa & ISA_MASK
objc4源码中ISA_MASK的值

# if __arm64__
// ARM64 simulators have a larger address space, so use the ARM64e
// scheme even when simulators build for ARM64-not-e.
#   define ISA_MASK        0x0000000ffffffff8ULL

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL

# else
#   error unknown architecture for packed isa
# endif
通过模拟源码中的数据结构,定义一个新的结构体,通过强制转换得到结构体的值,可以验证源码中结构体的组成。
struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
};
struct objc_object {
private:
    isa_t isa;
};
#define FAST_DATA_MASK          0x00007ffffffffff8UL
struct class_data_bits_t {
    friend objc_class;
    // Values are the FAST_ flags above.
    uintptr_t bits;
    class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
};
struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint16_t witness;
    class_rw_ext_t *extAlloc(const class_ro_t *ro, bool deep = false);
};
struct class_rw_ext_t {
    DECLARE_AUTHED_PTR_TEMPLATE(class_ro_t)
    class_ro_t_authed_ptr ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};
struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif
    union {
        const uint8_t * ivarLayout;
        Class nonMetaclass;
    };
    explicit_atomic name;// 类名
    // With ptrauth, this is signed if it points to a small list, but
    // may be unsigned if it points to a big list.
    void *baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
};

面试:OC类的信息存放在哪里?

  • 对象方法、属性、成员变量、协议,存放在class对象中
  • 类方法,存放在meta-class对象中
  • 成员变量的值存放在instance对象中

面试:isa指针指向哪里?

  • instance对象的isa指向class对象
  • class的isa指向meta-class对象
  • meta-class的isa指向基类的meta-class对象
  • 基类的meta-class的isa指向它自己

你可能感兴趣的:(iOS isa指针笔记)