在探索oc对象本质前,先了解一个编译器:clang
Clang
-
clang
是一个由Apple
主导编写,基于LLVM
的C/C++/OC的编译器
-
主要是用于
底层编译
,将一些文件``输出
成c++文件
,例如main.m
输出成main.cpp
,其目的是为了更好的观察底层
的一些结构
及实现
的逻辑,方便理解底层原理。
探索对象本质
- 在
main
中自定义一个类LGPerson
,有一个属性name
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation LGPerson
@end
- 通过终端,利用
clang
将main.m
编译成main.cpp
,有以下几种编译命令,这里使用的是第一种
//1、将 main.m 编译成 main.cpp
clang -rewrite-objc main.m -o main.cpp
//2、将 ViewController.m 编译成 ViewController.cpp
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot / /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.7.sdk ViewController.m
//以下两种方式是通过指定架构模式的命令行,使用xcode工具 xcrun
//3、模拟器文件编译
- xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
//4、真机文件编译
- xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main- arm64.cpp
-
打开编译好的main.cpp,找到
LGPerson
的定义,发现LGPerson
在底层会被编译成struct
结构体-
LGPerson_IMPL
中的第一个属性 其实就是isa
,是继承自NSObject
,属于伪继承
,伪继承的方式
是直接将NSObject
结构体定义为LGPerson
中的第一个属性
,意味着LGPerson
拥有NSObject
中的所有成员变量
。 -
LGPerson
中的第一个属性NSObject_IVARS
等效于NSObject
中的isa
-
如下图所示
clang编译后的LGPerson
通过上述分析,理解了OC对象的本质,但是看到NSObject
的定义,会产生一个疑问:为什么isa
的类型是Class
?
- 在iOS-底层原理 02:alloc & init & new 源码分析文章中,提及过
alloc
方法的核心之一的initInstanceIsa
方法,通过查看这个方法的源码实现,我们发现,在初始化isa
指针时,是通过isa_t
类型初始化的, - 而在
NSObject
定义中isa的类型是Class
,其根本原因是由于isa
对外反馈的是类信息
,为了让开发人员更加清晰明确
,需要在isa
返回时做了一个类型强制转换
,类似于swift
中的as
的强转。源码中isa
的强转
如下图所示
总结
所以从上述探索过程中可以得出:
-
OC对象的本质
其实就是结构体
-
LGPerson
中的isa
是继承自NSObject
中的isa