
首先要了解一下clang
Clang 是一個(gè)C語(yǔ)言、C++、Objective-C語(yǔ)言的輕量級(jí)編譯器。源代碼發(fā)布于BSD協(xié)議下。Clang將支持其普通lambda表達(dá)式、返回類型的簡(jiǎn)化處理以及更好的處理constexpr關(guān)鍵字。
Clang是一個(gè)由Apple主導(dǎo)編寫,基于LLVM的C/C++/Objective-C編譯器
2013年4月,Clang已全面支持C++11標(biāo)準(zhǔn),并開始實(shí)現(xiàn)C++1y特征(也就是C++14,這是C++的下一個(gè)小更新版本)。Clang將支持其普通lambda表達(dá)式、返回類型的簡(jiǎn)化處理以及更好的處理contexpr關(guān)鍵字。[2]
Clang是一個(gè)C++編寫、基于LLVM、發(fā)布于LLVM BSD許可證下的C/C++/Objective-C/Objective-C++編譯器,它與GNU C語(yǔ)言規(guī)范幾乎完全兼容(當(dāng)然,也有部分不兼容的內(nèi)容,包括編譯命令選項(xiàng)也會(huì)有點(diǎn)差異),并在此基礎(chǔ)上增加了額外的語(yǔ)法特征,比如C函數(shù)重載(通過(guò)__attribute__((overloadable))來(lái)修飾函數(shù),其目標(biāo)(之一)就是超越GCC。
clang -rewrite-objc main.m -o main.cpp 把目標(biāo)文件編譯成c++文件
UIKit報(bào)錯(cuò)問(wèn)題
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安裝的時(shí)候順帶安裝了xcrun命令,xcode命令在clang的基礎(chǔ)上進(jìn)行了一些封裝,要更好用一些
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 (真機(jī))
由于OC是基于C和C++上層的超體,可通過(guò)Clang還原OC在底層的實(shí)現(xiàn)
新建一個(gè)項(xiàng)目創(chuàng)建一個(gè)YDPerson類并在main.m中創(chuàng)建YDPerson對(duì)象如下


打開item客戶端,并cd到main.m文件所在目錄執(zhí)行xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m -o main.cpp,可看到在main.m文件生成了main.cpp的文件,打開main.capp文件查找YDPerson的對(duì)象

通過(guò)編譯發(fā)現(xiàn)YDPerson被編譯成了YDPerson_IMPL,那就是說(shuō)對(duì)象底層的本質(zhì)就是結(jié)構(gòu)體,真的嗎?我們可以再添加一個(gè)屬性nickName的屬性測(cè)試一下


再次編譯后發(fā)現(xiàn)新添加的屬性在struct YDPerson_IMPL中出現(xiàn)了,再次證實(shí)對(duì)象在底層的本質(zhì)是結(jié)構(gòu)體

結(jié)構(gòu)體中的struct NSObject_IMPL NSObject_IVARS其實(shí)就是從NSObject繼承的isa,而在代碼中有typedef struct objc_object LGPerson這樣的代碼,即LGPerson是struct objc_object這樣的類型這是什么含義呢,其實(shí)在OC層面的繼承是NSObject,而objc在底層真正的實(shí)現(xiàn)是objc_object,那么類Class在底層是什么類型呢?


通過(guò)編譯后的源碼發(fā)現(xiàn)Class其實(shí)是struct objc_class *類型,而objc_class其實(shí)繼承于objc_object,這在objc的底層源碼中是可以找到的

id 其實(shí)是struct objc_object *類型,這也是為什么id類型不用*號(hào)的原因

而_I_YDPerson_nickName就是屬性nickName的getter方法,_I_YDPerson_setNickName_就是屬性nickName的set方法,那方法里的self+ OBJC_IVAR_$_YDPerson$_nickName又是什么呢?
因?yàn)閷?duì)象的內(nèi)存在堆上,對(duì)象的內(nèi)存存儲(chǔ)的就是isa和nickName這樣一個(gè)一個(gè)的成員變量,而要想獲取到nickName的值就得先獲取到對(duì)象YDPerson在內(nèi)存的首地址地址,然后通過(guò)內(nèi)存相應(yīng)的大小找到nickName所在的存儲(chǔ)空間,最后再獲取里面的值,那nickName的set方法為什么不是通過(guò)內(nèi)存平移的形式而是調(diào)用了objc_setProperty呢,其實(shí)這是系統(tǒng)在底層對(duì)copy修飾的屬性進(jìn)行了單獨(dú)的處理,在后面章節(jié)中會(huì)來(lái)驗(yàn)證。