![](/img/trans.png)
[英]Using defined constants in functions and structs without them going blank (Swift)
[英]Swift constants (with a calculation) in functions?
這是一個簡單的Swift函數
fileprivate func test()->String{
let c = Array("abc".characters)
let k = UInt32(c.count)
let r = Int(arc4random_uniform(k))
return String(c[r])
}
(我選擇此示例是因為,顯然,您可能會調用數十億次才能生成某種輸出;因此您可能會擔心設置兩個常量時的性能。)
請注意,它必須做一些計算才能得到c
,而實際上要獲得k
則必須使用c
。
我的問題很簡單:每次調用此函數
test()
test()
test()
實際上, 我每次調用它時都會計算k
和/或c
,或者實際上它們僅計算一次嗎?
(如果“僅一次”,那么出於好奇:是我第一次調用該函數嗎?或者編譯器安排在啟動時分別完成它?或者為此,它知道它可以在編譯期間計算它們嗎? ?)
我經常使用全局計算的屬性,就像這樣
let basicDF : DateFormatter = {
print("this will only be done once per launch of the app")
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
(也許使用fileprivate
)如果上述問題的答案是“否,則每次調用test時都會計算c
和'k'”,那么在那種情況下,如何在函數內放置一種靜態計算屬性?
不,在您的特定情況下,編譯器當前不會將c
和/或k
優化為僅求值一次的常量表達式(這可以通過在優化的構建中檢查IR來看出)–盡管這可能會隨語言的未來版本。
但是,值得注意的是,它目前可以針對更簡單的表達式執行此操作,例如:
func foo() -> Int {
return 2 + 4
}
編譯器可以在編譯時評估加法,因此該函數僅return 6
(然后可以內聯)。 但是,當然,如果您實際上已經將給定功能確定為性能瓶頸,則首先應該只擔心這種優化。
在函數中獲取靜態常量的一個不錯的技巧是在函數范圍內定義一個具有靜態屬性的無大小寫enum
,您可以在其中定義常量表達式:
func test() -> String {
enum Constants {
static let c = Array("abc".characters)
static let k = UInt32(c.count)
}
let r = Int(arc4random_uniform(Constants.k))
return String(Constants.c[r])
}
現在, c
和k
的初始化程序表達式都將只被評估一次,這將在首次使用它們時(即,在首次調用該函數時)進行。
當然,正如您所展示的,您可以使用立即評估的閉包以具有多行初始化表達式:
enum Constants {
static let c: [Character] = {
// ...
return Array("abc".characters)
}()
// ...
}
我認為您應該假設每次都計算c
和k
。 可能會將計算優化為編譯器的實現細節,但是如果您是我,我不會指望這一點。
Swift沒有等效於C static
局部變量(即,函數內的“自動”變量,其值在兩次調用之間保持不變)。
如果您真的想確保k
僅計算一次,請使其為真正的常量(即在類級別)。 當然,您還需要對c
進行相同的操作,這在以后的計算中需要。 在這種情況下,這似乎是一個愚蠢的示例,但是當創建的東西很重時,例如在反復使用的圖像或視圖時,我經常這樣做:
class MyView : UIView {
lazy var arrow : UIImage = self.arrowImage()
func arrowImage () -> UIImage {
// ... big image-generating code goes here ...
}
}
我arrowImage()
調用arrowImage()
,直到我對自己說,等等,我可以將其設為一個常數(在這里表示為lazy var
)並僅對其進行一次計算,即第一次訪問arrow
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.