OC编译的过程
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指针
// test为对象
TestClass *test = [[TestClass alloc] init];
- 类对象(对象的类)
class,内存存放ISA指针、superClass指针、类的属性信息@property、类的对象方法信息instance method、类的协议信息protocol和类的成员变量信息ivar
#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
#import <objc/runtime.h>
// metaClass为元类对象
Class metaClass = object_getClass([TestClass class]);
// 判断是不是元类对象的方法
BOOL result = class_isMetaClass(metaClass);
isa指针 和 superClass指针 指向哪里
superClass指针指向规则:指向父类,没有指向nilsuperClass指针特殊规则:基类NSObject的meta-class的superClass指向基类Classisa指针指向规则:instance对象 -> class对象 -> meta-class对象isa指针特殊规则:元类对象的isa指针,指向其基类的meta-classisa指针其实并不是直接指向目标内存,需要进行一次位运算,isa指针&ISA_MASK才是真实地址,而superClass指针是直接指向,
- 如果是想调用
Subclass对象的rootClass类方法,则路径为:Subclass对象.isa指针 -> subclass.isa指针 -> subclass(meta).superClass -> superClass(meta).superClass -> rootClass -> 类方法 - 并且,根据调用路径,如果没有该类方法,会调用
rootClass同名的对象方法
附录
查看runtime源码
Objective-C 代码转换为 C++/C 代码
- 将
m文件转为C++文件,使用终端命令行 - 命令行
cd到m文件所在的地址 - 执行转化代码,生成指定的
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_getClass 和 objc_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)
- 传入字符串类名
- 返回对应的类对象