是否每次访问计算属性时都会对其进行评估?

zhu*_*ber 6 properties swift computed-properties

我有两个关于Swift计算属性的问题.

是否每次访问计算属性时都会对其进行评估?或者它们存储在某个地方以供将来访问?

这是什么类型的财产,因为我无法谷歌:

let navigationController: UINavigationController = {
   var navigator = UINavigationController()
   navigator.navigationBar.translucent = false
   return navigator
}()
Run Code Online (Sandbox Code Playgroud)

每次访问时都会评估它吗?

Luc*_*tti 14

那不是计算属性.

let navigationController: UINavigationController = {
   var navigator = UINavigationController()
   navigator.navigationBar.translucent = false
   return navigator
}()
Run Code Online (Sandbox Code Playgroud)

它只是一个存储的属性,填充了此代码块返回的值的结果.

var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
Run Code Online (Sandbox Code Playgroud)

在实例化类的实例时执行该块.只有一次.

写这个

struct Person {
    let name: String = {
        let name = "Bob"
        return name
    }() // <- look at these
}
Run Code Online (Sandbox Code Playgroud)

相当于

struct Person {
    let name: String
    init() {
        self.name = "Bob"
    }
}
Run Code Online (Sandbox Code Playgroud)

恕我直言,第一种方法更好,因为:

  • 它允许您在同一"空间"中声明和填充属性
  • 它更清楚
  • 如果您有多个初始值设定,可以防止重复代码

注意#1:在属性中存储闭包

正如dfri在下面的评论中指出的那样,代码块确实以().这意味着将评估代码并将结果分配给属性.

另一方面,如果我们删除()块的末尾,我们得到一些不同的东西,事实上块不被评估.在这种情况下,Swift尝试为stored closure属性分配一个.这将产生编译错误,因为属性具有此类型UINavigationController.

使用正确的语法,我们可以在属性中放置一个闭包.

struct Person {
    let sayHello: ()->() = { print("Hello") }
}
Run Code Online (Sandbox Code Playgroud)

现在我们有一个sayHello包含闭包的属性.闭包接收0参数并返回Void.

let bob = Person()
bob.sayHello // this does NOT execute the code inside closure
bob.sayHello() // this does execute the code in the closure and does print the message
Run Code Online (Sandbox Code Playgroud)

注意#2:让我们谈谈计算属性

因此,我们明确表示,在这个问题上的代码是不是一个Computed Property.但是,正如EmilioPelaez在下面的另一条评论中指出的那样,我们还应该声明每次访问Computed Property都会评估a .

在下面的示例中,我创建了一个Computed Property age.正如您每次调用它时所看到的那样,块中的代码也会被执行.

计算属性的示例(age)

在此输入图像描述

  • 是的,代码只执行一次.您可以在该代码块中添加`print("Test")`并进行验证. (2认同)
  • 可能值得一提的是,在最后一个大括号之后的`()`是关键(通过运行匿名闭包块初始化`navigationController`属性一次).例如删除这个最后的`()`和_"略微"_修改顶行为`let navigationController :() - >(UINavigationController)= {...`将产生一个存储的闭包,它返回带有`的`UINavigationController`实例.半透明=假.这个闭包又可以用来代替上面的匿名块,即用闭包名而不是`{...}`块:`let myNavigationController = navigationController()`. (2认同)