首先要了解一下clang
Clang
是一个C
语言、C++
、Objective-C
语言的轻量级编译器。源代码发布于BSD
协议下。Clang
将支持其普通lambda
表达式、返回类型的简化处理以及更好的处理constexpr
关键字。
Clang
是一个由Apple
主导编写,基于LLVM
的C/C++/Objective-C
编译器
2013
年4
月,Clang
已全面支持C++11
标准,并开始实现C++1y
特征(也就是C++14
,这是C++
的下一个小更新版本)。Clang
将支持其普通lambda
表达式、返回类型的简化处理以及更好的处理contexpr
关键字。[2]
Clang
是一个C++
编写、基于LLVM
、发布于LLVM BSD
许可证下的C/C++/Objective-C/Objective-C++
编译器,它与GNU
C
语言规范几乎完全兼容(当然,也有部分不兼容的内容,包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特征,比如C函数重载(通过__attribute__((overloadable))
来修饰函数,其目标(之一)就是超越GCC
。
clang -rewrite-objc main.m -o main.cpp
把目标文件编译成c++
文件
UIKit
报错问题
clang -rewrite-objc-fobjc-arc-runtime=iOS-13.0.0-isysroot/Applications/Xcode.app/Contens/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
xcode
安装的时候顺带安装了xcrun
命令,xcode
命令在clang
的基础上进行了一些封装,要更好用一些
xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m -o main.cpp
(模拟器)
xcrun -sdk iphones clang -arch arm64 -rewrite-objc main.m -o main.cpp
(真机)
由于OC
是基于C
和C++
上层的超体,可通过Clang
还原OC
在底层的实现
新建一个项目创建一个YDPerson
类并在main.m
中创建YDPerson
对象如下
打开item
客户端,并cd
到main.m
文件所在目录执行xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m -o main.cpp
,可看到在main.m
文件生成了main.cpp
的文件,打开main.capp
文件查找YDPerson
的对象
通过编译发现YDPerson
被编译成了YDPerson_IMPL
,那就是说对象底层的本质就是结构体,真的吗?我们可以再添加一个属性nickName
的属性测试一下
再次编译后发现新添加的属性在struct YDPerson_IMPL
中出现了,再次证实对象在底层的本质是结构体
结构体中的struct NSObject_IMPL NSObject_IVARS
其实就是从NSObject
继承的isa
,而在代码中有typedef struct objc_object LGPerson
这样的代码,即LGPerson
是struct objc_object
这样的类型这是什么含义呢,其实在OC
层面的继承是NSObject
,而objc
在底层真正的实现是objc_object
,那么类Class
在底层是什么类型呢?
通过编译后的源码发现Class
其实是struct objc_class *
类型,而objc_class
其实继承于objc_object
,这在objc
的底层源码中是可以找到的
id
其实是struct objc_object *
类型,这也是为什么id
类型不用*
号的原因
而_I_YDPerson_nickName
就是属性nickName
的getter
方法,_I_YDPerson_setNickName_
就是属性nickName
的set
方法,那方法里的self+ OBJC_IVAR_$_YDPerson$_nickName
又是什么呢?
因为对象的内存在堆上,对象的内存存储的就是isa
和nickName
这样一个一个的成员变量,而要想获取到nickName
的值就得先获取到对象YDPerson
在内存的首地址地址,然后通过内存相应的大小找到nickName
所在的存储空间,最后再获取里面的值,那nickName
的set
方法为什么不是通过内存平移的形式而是调用了objc_setProperty
呢,其实这是系统在底层对copy
修饰的属性进行了单独的处理,在后面章节中会来验证。