iOS:底层原理之 Objective-C 的本质

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;        // 成员变量列表
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值