譯 Swift 裡的強制 inline 註解

2021-09-24 07:53:55 字數 2626 閱讀 8963

譯文出自:掘金翻譯計畫

譯者:iweslie

校對者:cloxnu

在程式設計中,函式內聯是一種編譯器優化技術,它通過使用方法的內容替換直接呼叫該方法,就相當於假裝該方法並不存在一樣,這種做法在很大程度上優化了效能。

例如,請看一下**:

func

calculateandprintsomething()

print("準備列印一些數字")

calculateandprintsomething()

print("完成")

複製**

假設calculateandprintsomething()沒有在其他任何地方使用過,很明顯該方法不需要存在於編譯後的二進位制檔案中,它存在的目的只是為了使你更加易於閱讀。

通過使用函式內聯,swift 編譯器可以通過將呼叫這個方法替換為呼叫它裡面的具體內容,從而消除那些不必要的開銷:

// 上面的示例轉化為編譯後二進位制版本

print("準備列印一些數字")

var num = 1

num *= 10

num /= 5

print("我的數字:\(num)")

print("完成")

複製**

基於你選擇的優化級別,這個過程由 swift 編譯器自動完成的,通過支援內聯來優化速度(-o),或者進行內聯來優化二進位製包的大小(-osize),因為內聯乙個經常呼叫且內容很多的方法會導致大量的重複**和更大的二進位製包。

儘管編譯器可以自己進行內聯,不過你還是可以 swift 中使用@inline註解來強制內聯,它有兩種用法:

@inline(__always):如果可以的話,指示編譯器始終內聯方法。

@inline(never):指示編譯器永不內聯方法。

現在你可能會問:到底怎麼選擇呢?

根據蘋果工程師的說法,答案基本上是 never。儘管該屬性可用於公共或廣泛使用的 swift 源**,但它還沒有正式支援公共使用。它從來沒有打算過要公開,jordan rose 也曾說到:設定它不被公開是有原因的。如果你要使用它,可能會出現許多已知和未知的問題。

但由於該屬性可以公開使用,為了學習新的東西,我會去嘗試一下它,而且我實際上發現了這個註解在 ios 專案中一些很實用的地方。

編譯器將根據專案的優化設定做出內聯決策,但在某些情況下,你可能需要一種方法來手動決策。這時@inline就可以幫助到你。

例如,在優化速度時,似乎編譯器會對一些內容並不是很短的方法進行內聯,從而導致二進位制大小增加。在這種情況下,@inline(never)可用於防止這個,同時保證二進位制檔案的速度。

另乙個更實際的例子是,你可能想防止黑客接觸到乙個包含某種敏感資訊的方法,它是否會使**變慢或包變大都無關緊要。你肯定會嘗試混淆你的**來使**更難理解,或者可以選擇混淆工具,例如 swiftshield,但@inline(__always)可以輕鬆實現這一點而同時不會損害你的**,我將在下面詳細介紹了這個例子:

func

isusersubscribed

() -> bool

func

play

(song: song)

else

}複製**

現在看看給isusersubscribed(_ :)新增了@inline(__always)後會發生什麼:

@inline(__always) func

isusersubscribed

() -> bool

func

play

(song: song)

else

}複製**

同樣的play(_:)方法裡現在不包括對訂閱狀態的判斷。這個方法呼叫完全被其內部的 「複雜的驗證」 所取代,這樣反編譯後看起來變得更加複雜,訂閱也更加難以破解。

好處是,由於每次呼叫isusersubscribed(_:)都被複雜的驗證取代,因此就沒有一種方法可以解鎖應用程式的整個訂閱,黑客現在必須破解每乙個進行驗證的方法。當然,多處的重複的**也意味著我們的二進位制檔案會變得更大。

請注意,使用@inline(__always)並不能保證編譯器會真正內聯你的方法。它的規則是未知的,例如在無法避免動態派發的情況下就無法進行內聯。

由於@inline沒有得到官方支援,你真的不應該在實際的專案中使用它,這篇文章使用它的目的只是為了學習新東西。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計畫 對譯文進行修改並 pr,也可獲得相應獎勵積分。文章開頭的本文永久鏈結即為本文在 github 上的 markdown 鏈結。

譯 Swift 上的高效能陣列

譯文出自 掘金翻譯計畫 譯者 jingzhilehuakai 校對者 rickeyboy cbangchen 對於日常應用開發,考慮陣列效能是一件不會經常發生的事。如果你正在實現需要擴充套件的演算法,也許高效能陣列就能出現在你腦海中。也許你正在寫更偏向於底層的 比如乙個框架,這時任何的效能缺陷都會產...

強制解包看 Swift 的設計

property nonatomic,copy nsstring foo 它轉成 swift 就變成了這樣 var foo string 這樣看上去合情合理。swift 中有 string?和 string 兩種形式,但 oc 中沒有 nsstring?和 nsstring 當 swift 無法區分...

強制解包看 Swift 的設計

1 property nonatomic,copy nsstring foo 它轉成 swift 就變成了這樣 var foo string 這樣看上去合情合理。swift 中有 string?和 string 兩種形式,但 oc 中沒有 nsstring?和 nsstring 當 swift 無法...