Objective-C 的本质
Objective-C —> C/C++ —> 汇编语言 —> 机器语言
Objective-C 是基于 C/C++ 的数据结构实现的。
将 Objective-C 代码转化为 C/C++代码:
xcrun -sdk iphoneos clang -rewrite-objc -arch arm64 main.m -o main.cpp
模拟器(i386),32bit(armv7),64bit(arm64)
汇编:compile
实现:implementation
一个 NSObject 对象占用多少个字节?
NSObject 的底层实现是一个只具有一个成员变量 Class *isa 的结构体,Class 为指向结构体的指针。
通过 import <objc/runtime.h> 的 class_getInstanceSize 方法可以获得一个 NSObject 实例对象的成员变量占 8 个字节的内存。
通过 import <malloc/malloc.h> 的 malloc_size 方法可以获得一个 NSObject 指针占用内存的大小为16个字节。
OC 跟 C 指针类型之间进行转换需要加桥接(__bridge)
lldb 指令 memory read/write 内存 value(write 时需要)
NSObject 的地址值为结构体成员变量 Class isa 的地址值。
内存对齐:结构体的大小必须是最大成员大小的倍数。
Objective-C 对象的分类
主要分为3类:
instance 对象(实例对象)
- 在内存中存储的信息包括:
- isa 指针
- 其他成员变量
class 对象(类对象)
- 在内存中存储的信息包括:
- isa 指针
- superclass 指针
- 类的属性信息(@property)
- 类的对象方法信息(instance method)
- 类的协议信息(protocol)
- 类的成员变量信息(ivar)
- 所有的 class 类都是同一个对象,在内存中有且只有一个 class 对象
- 通过 runtime 的 object_getClass(instance对象) 获得类对象
- 每个实例对象只有一个类对象。
Class *class = [[[NSObject class] class] class];
- 再多的 class 对象返回的都是类对象。
meta-class 对象(元类对象)
- 例:meta-data 元数据:描述数据的数据
- 通过runtime的object_getClass(class对象)获得元类对象
- 每个类对象在内存中有且只有一个元类对象。
- 元类对象和类对象在内存中的内存结构是一样的,但用途不一样,在内存中存储的信息包括:
- isa 指针
- superclass 指针
- 类的类方法信息(class method)
- ……(类对象的结构信息,不过值是 null 的)
object_getClass 是通过传入一个类名,返回一个类对象。如果类不存在就返回 nil。
[person personInstanceMethod]; 可以理解为 objc_msgSend(person, @selector(personInstanceMethod));
instance 的 isa指针指向 class
当调用对象方法时,通过 instance 的 isa 找到 class,最后找到对象方法的实现进行调用。
class 的 isa 指向 meta-class
当调用类方法时,通过 class 的 isa 找到 meta-class,最后找到类方法的实现进行调用。
Instance 的 isa指针地址 & ISA_MASK(位运算) 得到 class 的地址
class 的 isa指针地址 & ISA_MASK(位运算) 得到 meta-class 的地址
ISA_MASK 的值自从 64bit 开始,isa需要进行一次位运算,才能计算出真实的地址。
if __arm64__
define ISA_MASK 0x0000000ffffffff8ULL
elif __x86_64__
define ISA_MASK 0x00007ffffffffff8ULL
endif
窥探 struct objc_class 的结构
struct objc_class : objc_object {
// Class ISA; // 由于 objc_class 集成自 objc_object 在objc_object 中包含 ISA指针的调用获取,可以调用父类的 ISA() 获得
Class superclass; // 父类
cache_t cache; // 对象缓存
class_data_bits_t bits; // 类对象信息的具体描述
class_rw_t *data() { // 见下方
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
class_rw_t:
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint32_t version;
const class_ro_t *ro; // 见下方
method_array_t methods; // 方法列表
property_array_t properties; // 属性列表
protocol_array_t protocols; // 协议列表
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
}
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; // 成员变量列表
}