2017-10-17 64 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方法用作目标时被初始化。类可以意识到它是没有初始化其属性的目标)也许是这样?) –