2017-10-17 119 views
2

爲什麼在早些時候,當我們在像這個例子那樣的計算屬性中調用self時,我們需要編寫lazy var,但現在我們不必這樣做。爲什麼?計算屬性中的自調用

let(lazy var in earlier times) pauseButton: UIButton = { 
    let button = UIButton(type: .system) 
    let image = UIImage(named: "pause") 
    button.setImage(image, for: .normal) 
    button.translatesAutoresizingMaskIntoConstraints = false 
    button.tintColor = .white 
    button.addTarget(self, action: #selector(handlePause), for: .touchUpInside) 

    return button 
    }() 
+0

你還有事,我只是粘貼你的代碼的Xcode 9圍繞一類包裹,並沒有組合物1因爲它找不到'self'。 –

+0

只是爲了確保我知道了,你的意思是'self.handlePause'它是正確的嗎? –

+0

@BrunoRocha我把這段代碼片段粘貼到Xcode 9上,它對我來說工作得很好。 –

回答

2

我認爲這是一個誤解,這是你的代碼段提到的是一個計算的財產!它只是一個已存儲的財產已被封閉初始化; As mentioned in the Swift Initialization - Setting a Default Property Value with a Closure or Function

If a stored property’s default value requires some customization or setup, you can use a closure or global function to provide a customized default value for that property. Whenever a new instance of the type that the property belongs to is initialized, the closure or function is called, and its return value is assigned as the property’s default value.

你可以檢查:Difference between computed property and property set with closure。是的pauseButton會被關閉,甚至沒有使用它,如果你嘗試檢查它(在它添加斷點)來執行,

注意,你會發現這一點。我認爲這是而不是你期待什麼 - 而不是你瞄準什麼 - 所以你應該聲明它爲lazy var而不是let

然而,

指同一Swift documentation

If you use a closure to initialize a property, remember that the rest of the instance has not yet been initialized at the point that the closure is executed. This means that you cannot access any other property values from within your closure, even if those properties have default values. You also cannot use the implicitselfproperty, or call any of the instance’s methods.

言下之意是:

class MyViewController: UIViewController { 
    let btnTitle = "pause" 

    let pauseButton: UIButton = { 
     let button = UIButton(type: .system) 
     let image = UIImage(named: btnTitle) 
     button.setImage(image, for: .normal) 
     button.translatesAutoresizingMaskIntoConstraints = false 
     button.tintColor = .white 
     button.addTarget(self, action: #selector(handlePause), for: .touchUpInside) 

     return button 
    }() 

    func handlePause() { } 
} 

威爾給出的let image = UIImage(named: btnTitle)的錯誤:

enter image description here

這也應該適用於任何其他實例成員,例如,如果你想嘗試添加view.addSubview(button)到關閉,你會得到同樣的錯誤view實例成員。

但對於一個原因(我不知道爲什麼),與選擇的工作似乎是一個特例,因爲button.addTarget(self, action: #selector(handlePause), for: .touchUpInside)對我(的Xcode 9.0)工作得很好,但如果你想添加self它,因爲:

button.addTarget(self, action: #selector(self.handlePause), for: .touchUpInside) 

你會得到以下錯誤:

enter image description here

+0

你是驚人的),但它仍然不透明,但更清晰的'不透明')也許我們不能使用self.handlePause選擇器,因爲(當然)其餘實例尚未初始化(即使功能不知道如何創建或寫入機器代碼或smith其他),但我們可以在存儲屬性關閉內的addTarget方法中提到self。我認爲(也許這是錯誤的)類不需要被addTarget方法用作目標時被初始化。類可以意識到它是沒有初始化其屬性的目標)也許是這樣?) –