计算属性中的自调用

Nin*_*nja 3 ios swift computed-properties

为什么在早些时候,当我们像这个例子一样在计算属性中调用 self 时,我们需要编写惰性变量,但现在我们不必这样做了。为什么?

   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
    }()
Run Code Online (Sandbox Code Playgroud)

Ahm*_*d F 6

我认为有一个误解,即您在代码片段中提到的不是计算属性!它只是一个由闭包初始化的存储属性正如 Swift 初始化 - 使用闭包或函数设置默认属性值中所述

如果存储属性的默认值需要一些自定义或设置,您可以使用闭包或全局函数为该属性提供自定义默认值。每当初始化属性所属类型的新实例时,就会调用闭包或函数,并将其返回值分配为属性的默认值。

您可以检查:计算属性和使用closure 设置的属性之间的差异

请注意,pauseButton即使不使用它,也将执行闭包,如果您尝试检查它(在其中添加断点),您会注意到这一点。我认为这不是您的期望 - 而不是您的目标 - 所以您应该将其声明为lazy var而不是let.

然而,

参考相同的Swift 文档

如果您使用闭包来初始化属性,请记住,在执行闭包时,实例的其余部分尚未初始化。这意味着您无法 从闭包中访问任何其他属性值,即使这些属性具有默认值。您也不能使用隐式 属性或调用任何实例的方法self

暗示:

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() { }
}
Run Code Online (Sandbox Code Playgroud)

将给出一个错误let image = UIImage(named: btnTitle)

在此处输入图片说明

这也应该适用于任何其他实例成员,例如,如果您尝试添加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)
Run Code Online (Sandbox Code Playgroud)

你会得到以下错误:

在此处输入图片说明