函數(shù)內聯(lián)
函數(shù)內聯(lián)是一種編譯器技術優(yōu)化,它通過使用方法的內容替換直接調用該方法,從而優(yōu)化性能皂甘。
1)將確保有時內聯(lián)函數(shù)。它是默認行為悼凑,我們無需執(zhí)行任何操作偿枕,Swift編譯器可能會自動內聯(lián)函數(shù)作為優(yōu)化。
2)always - 將確保始終內聯(lián)函數(shù)户辫。通過在函數(shù)前添加@inline(__always),來實現(xiàn)此行為
3)never - 將確保永遠不會內聯(lián)函數(shù)渐夸。這可以通過在函數(shù)前添加@inline(never)來實現(xiàn)。
4)如果函數(shù)很長并且想避免增加代碼段大小渔欢,請使用@inline(never)
如果對象只在聲明的文件中可見墓塌,可以用 private 或 fileprivate進行修飾。編譯器會對private或fileprivate對象進行檢查,確保沒有其他繼承關系的情形下桃纯,自動打上final標記酷誓,進而使得對象獲得靜態(tài)派發(fā)的特性(fileprivate:只允許在定義的源文件中訪問,private:定義的聲明中訪問 )
存儲屬性
存儲屬性是一個作為特定類和結構實例一部分的常量或變量态坦。存儲屬性要么是變量存儲屬性(由var關鍵字引入)要么是常量存儲屬性(由let關鍵字引入)盐数。
let用來聲明常量,常量的值一旦設置好便不能再被更改伞梯;
var用來聲明變量玫氢,變量的值可以在將來設置為不同的值。
如果在struct里有l(wèi)et age和var name谜诫,這age和name都是不可以被修改的漾峡。在class里有l(wèi)et age和var name,這個age是不可以修改喻旷,但是name用var定義的是可以修改的生逸。
我們通過sil查看let和var區(qū)別:var和let都是hasStorage存儲屬性,var有get和set且预,但是let只有get槽袄。
計算屬性
計算屬性并不存儲值,他們提供getter和setter來修改和獲取值锋谐,對于存儲屬性來說可以是常量或變量遍尺,但計算屬性必須定義為變量。與此同時我們書寫計算屬性時候必須包含類型涮拗,因為編譯器需要知道期望返回值是什么乾戏。
屬性觀察者
屬性觀察者會觀察用來觀察屬性值的變化,一個willset當屬性將被改變調用三热,即使這個值與原有的值相同鼓择,而didset在屬性已經(jīng)改變之后調用。他們的語法類似于getter和setter就漾。
這里我們在使用屬性觀察器的時候惯退,需要注意的一點是在初始化期間設置屬性時不會調用willset和didset觀察者;只有在完全初始化的實例分配新值時才會調用它們从藤。
下面圖中willset和didset是不會調用的催跪,因為在init中。
如果有父類的話夷野,其調用順序為 override willset --> wiliest --> 賦值 --> didst --> override didset
延遲存儲屬性
1)延遲存儲屬性的初始值在其第一次使用時才進行計算懊蒸。
2)用關鍵字lazy來標識一個延遲存儲屬性。
通過下面可以看出悯搔,在沒有使用到age時候其地址為0x000000000000骑丸,當被使用的時候其地址值為0x000000000012,第一次使用才加載。
類型屬性static
1)類型屬性其實就是一個全局變量
2)類型屬性只會被初始化一次
Swift里的單例的寫法
在這里用到的是static let去定義通危,但是只有這個是不行的铸豁,需要加個private init(){}
屬性在Mahco文件的位置信息
Metadata 的元數(shù)據(jù)結構,如下:
之前在方法調度的過程中我們認識了typeDescriptor菊碟,這里面記錄了V-table的相關信息节芥,接下來我們需要認識一下typeDescriptor中的fieldDescripto。
fieldDescriptor記錄了當前的屬性信息逆害,其中fieldDescriptor在源碼中的結構如下:
其中NumFields代表當前有多少個屬性头镊,F(xiàn)ieldRecords記錄了每個屬性的信息,F(xiàn)ieldRecords的結構體如下: