Objective-C对象、类对象、元类对象探究

169 阅读3分钟

OC编译的过程

架构图 .png

  • Objective-C 代码转换为 C++/C 代码
  • C++/C 代码调用 runtime 动态库的内容,runtime 动态库为底层库
  • C++/C 代码转为汇编语言,再转为机器语言

类和对象的本质都是结构体

  • OC 编写一个类,转为 C++,查看C++内容
  • Objective-C 代码转换为 C++/C 代码方法查看附录
// OC源码
@interface People : NSObject {
    @public
    int _count;
}
@end

// 转为C++,添加_IMPL后缀,生成对应结构体
// IMPL代表@implementation
// CPP文件代表CPlusPlus,C++
struct People_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _count;
};

// NSObject_IMPL内部存放ISA指针
struct NSObject_IMPL {
Class isa;
};

  • Class 相关查看 runtime 源码,这部分被 Apple 封装了,需要去官网下载,下载方法查看附录
// Class的类型
typedef struct objc_class *Class;

// objc_class源码
struct objc_class : objc_object {
    // Class ISA;              // ISA指针
    Class superclass;          // superClass指针
    cache_t cache;             // 方法缓存
    class_data_bits_t bits;    // 用于获取具体的类信息,例如方法列表,属性列表,协议列表
    // 其他省略
}

// objc_object源码
struct objc_object {
    // 里面相对复杂,总结就是存放一个ISA指针
    Class ISA;
    // 其他省略
}
    

对象、类对象、元类对象

  • 对象 instance,内存存放成员变量和 ISA指针

架构图.png

// test为对象
TestClass *test = [[TestClass alloc] init];
  • 类对象(对象的类) class,内存存放 ISA指针superClass指针、类的属性信息 @property、类的对象方法信息 instance method、类的协议信息 protocol 和类的成员变量信息 ivar

架构图.png

#import <objc/runtime.h>
// 方法一 objectClass为类对象
// Tip:[[TestClass class] class]获取的对象还是类对象
Class objectClass = [TestClass class];
// 方法二 objectClass为类对象
Class objectClass = object_getClass([[TestClass alloc] init]);
  • 元类对象(类的类) meta-class,内存存放 ISA指针superClass指针、类的方法信息 class method

架构图.png

#import <objc/runtime.h>
// metaClass为元类对象
Class metaClass = object_getClass([TestClass class]);
// 判断是不是元类对象的方法
BOOL result = class_isMetaClass(metaClass);

isa指针 和 superClass指针 指向哪里

  • superClass指针 指向规则:指向父类,没有指向 nil
  • superClass指针 特殊规则:基类 NSObjectmeta-classsuperClass 指向基类 Class
  • isa指针 指向规则:instance对象 -> class对象 -> meta-class对象
  • isa指针 特殊规则:元类对象的 isa指针 ,指向其基类的 meta-class
  • isa指针 其实并不是直接指向目标内存,需要进行一次位运算,isa指针&ISA_MASK 才是真实地址,而 superClass指针 是直接指向,

Pasted Graphic 3.png

  • 如果是想调用 Subclass对象rootClass类方法 ,则路径为:Subclass对象.isa指针 -> subclass.isa指针 -> subclass(meta).superClass -> superClass(meta).superClass -> rootClass -> 类方法
  • 并且,根据调用路径,如果没有该类方法,会调用 rootClass 同名的对象方法

附录

查看runtime源码

image.png 地址:github.com/apple-oss-d…

Objective-C 代码转换为 C++/C 代码

  • m文件 转为 C++ 文件,使用终端命令行
  • 命令行 cdm文件 所在的地址
  • 执行转化代码,生成指定的 cpp 文件
    // 直接根据MacOS系统生成CPP文件
    // 文件会比较大,不建议使用
    clang -rewrite-objc 目标文件.m -o 生成文件.cpp
    clang -rewrite-objc Test.m -o Test.cpp
    // 根据iOS系统ARM64生成CPP文件
    // 文件比较小,建议使用🌟
    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 目标文件.m -o 生成文件.cpp
    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc Test.m -o Test.cpp

object_getClassobjc_getClass 的区别

object_getClass(id obj)

  • 本质是返回 ISA指针对象
  • obj 可能是 instance对象class对象meta-class对象
  • 如果是 instance对象,返回 class对象
  • 如果是 class对象,返回 meta-class对象
  • 如果是 meta-class对象,返回 NSObject(基类)meta-class对象

objc_getClass (const char *aClassName)

  • 传入字符串类名
  • 返回对应的类对象