Object

Objective-C 中的对象

Obj-C 中的对象

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ae81bfb2-aecc-49ba-97d3-44117f694791/Untitled.png

NSObject 定了 isa 指针,用于指向 Class ,而 Class 本质上则是指向 objc_class 结构体的指针:

// NSObject.h @interface NSObject <NSObject> { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-interface-ivars" Class isa OBJC_ISA_AVAILABILITY; #pragma clang diagnostic pop }

Class 的本质则是指向 objc_class 结构体的指针,存放了 isasuperclass 、方法缓存等。

typedef struct objc_class *Class; // objc-runtime-new.h struct objc_class : objc_object { // Class ISA; // 父类指针 Class superclass; // 方法缓存 cache_t cache; // formerly cache pointer and vtable // 可读可写表(class_rw_t)等 class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags // ... }; // objc-private.h struct objc_object { private: // isa 指针 isa_t isa; // ... } struct class_data_bits_t { // Values are the FAST_ flags above. uintptr_t bits; class_rw_t* data() { return (class_rw_t *)(bits & FAST_DATA_MASK); } // ... }

bits 标志位作用:

  • 0 - 1 , FAST_IS_SWIFT_LEGACY ,是否来自 ABI 预稳定版本的 Swift ;
  • 1 - 2 , FAST_IS_SWIFT_STABLE ,是否来自 ABI 稳定版本的 Swift ;
  • 2 - 3 , FAST_HAS_DEFAULT_RR ,类或父类含有默认的持有或引用;
  • 3 - 47 , FAST_DATA_MASK ,指向 class_rw_t 结构体的指针;
  • 47 - 63 ,字节对齐,填 0 。

class_rw_t 是可读可写, Read-Write ,在运行时会进行调整,而 class_ro_t 是只读的,在编译期已经确定,无法调整。

struct class_rw_t { // Be warned that Symbolication knows the layout of this structure. uint32_t flags; uint32_t version; // 只读表的指针(const:不可修改指针指向内存空间中的数据) const class_ro_t *ro; // 方法、属性、协议信息,可用于运行时动态添加 method_array_t methods; property_array_t properties; protocol_array_t protocols; // ... };

class_ro_t 在编译时会被动态替换为 class_rw_t ,而 class_rw_t 则会通过指针指向 class_ro_t

struct class_ro_t { // 标志位 uint32_t flags; uint32_t instanceStart; // 实例大小 uint32_t instanceSize; #ifdef __LP64__ uint32_t reserved; #endif const uint8_t * ivarLayout; // 类名 const char * name; method_list_t * baseMethodList; protocol_list_t * baseProtocols; // 成员变量 const ivar_list_t * ivars; const uint8_t * weakIvarLayout; property_list_t *baseProperties; method_list_t *baseMethods() const { return baseMethodList; } };

从上面的 class_rw_tclass_ro_t 可以看出为什么 Category 不支持添加变量,因为 Category 相关方法和属性是添加到 class_rw_t 中的,而 class_ro_t 表示的示例大小和属性在编译时已经确定了,不支持在运行时进行修改。

基类:

isa 指针

Obj-C 中的 isa 指针

实例对象中的 isa 指向类对象,类对象中的 isa 指向元类对象,元类对象中的 isa 指向根元类对象(包括根元类对象也指向自己)。 isa_t 通过 union 来共享内存占用:

struct objc_object { private: isa_t isa; // ... } union isa_t { isa_t() { } isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bits; #if defined(ISA_BITFIELD) struct { ISA_BITFIELD; // defined in isa.h }; #endif }; // isa.h // ARM 64 # if __arm64__ # define ISA_MASK 0x0000000ffffffff8ULL # define ISA_MAGIC_MASK 0x000003f000000001ULL # define ISA_MAGIC_VALUE 0x000001a000000001ULL # define ISA_BITFIELD \ uintptr_t nonpointer : 1; \ uintptr_t has_assoc : 1; \ uintptr_t has_cxx_dtor : 1; \ uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \ uintptr_t magic : 6; \ uintptr_t weakly_referenced : 1; \ uintptr_t deallocating : 1; \ uintptr_t has_sidetable_rc : 1; \ uintptr_t extra_rc : 19 # define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18) // _uintptr_t.h #ifndef _UINTPTR_T #define _UINTPTR_T typedef unsigned long uintptr_t; #endif /* _UINTPTR_T */