你告诉编译器你想让
profileImageView
包含一个闭包。如果你想让profileImageView包含该闭包的
结果,你需要在后面加上括号来调用闭包:
lazy var profileImageView: UIImageView = {
return imageView
}()
注意闭包后面的括号。这将调用闭包并将其结果分配给变量`profileImageView`,在第一次引用该变量时。
编辑:
每当你看到`(<something>) -> type`这样的类型时,它就是一个闭包。`->`部分将参数与返回类型分隔开。Swift的错误消息可能很难解读,但这是一个提示,你返回的是一个闭包,而不是预期的内容。
编辑 #2:
请注意,在Swift中,与闭包定义的变量相关的有两个类似的结构:计算属性和延迟变量。
计算属性
计算属性的声明方式为
var computed: type { closure_returning_result }
在计算属性中没有等号。每次从计算属性请求一个值时,闭包代码都会运行,并且闭包的返回值将成为属性的新值。
懒加载变量的写法如下:
lazy var lazy: type = expression_returning_result
表达通常是一个闭包,但不一定非要是这样。一个常见的懒惰变量的形式会使用闭包,就像这样:
lazy var lazy: type = { closure_returning_result }()
在声明懒惰变量时,需要使用等号。如果你使用闭包给懒惰变量赋值,你需要在闭包后面加上括号,这样懒惰变量将被赋予闭包返回的值,而不是闭包本身。当@jameel在他的代码中忘记闭合括号时,就会出现这个问题。
考虑以下代码:
var counter = 1
var computed: Int {
counter += 1
return counter
}
lazy var lazy: Int = {
counter += 1
return counter
}()
print("lazy = \(lazy)")
print("lazy = \(lazy)")
print("lazy = \(lazy)")
print("computed = \(computed)")
print("computed = \(computed)")
print("computed = \(computed)")
这将打印输出:
lazy = 2
lazy = 2
lazy = 2
computed = 3
computed = 4
computed = 5
请注意,懒惰变量的值不会改变,但计算属性的值会改变。这是它们之间的关键区别。
懒惰变量在第一次被调用时进行评估,并且该值会“固定”。给出该值的表达式/闭包直到被调用时才会运行,而且只运行一次。
相比之下,计算属性始终使用闭包,每次请求计算属性的值时,都会执行该闭包。
编辑#3:(2023年9月28日)
还要注意,懒惰变量直到首次引用时才被初始化,这可能会产生后果。
如果您颠倒了上面的测试代码的顺序:
print("computed = \(aFoo.computed)")
print("computed = \(aFoo.computed)")
print("computed = \(aFoo.computed)")
print("lazy = \(aFoo.lazy)")
print("lazy = \(aFoo.lazy)")
print("lazy = \(aFoo.lazy)")
print("computed = \(aFoo.computed)")
print("lazy = \(aFoo.lazy)")
print("computed = \(aFoo.computed)")
输出将会是
computed = 2
computed = 3
computed = 4
lazy = 5
lazy = 5
lazy = 5
computed = 6
lazy = 5
computed = 7
通过这个示例代码,我们在调用计算属性3次之后才引用到`lazy`。一旦我们引用到`lazy`,它会递增`counter`并将该结果保存为其新值,永远不变。
如果我们再次引用`computed`,它会再次递增`counter`。
`lazy`的值在代码执行的整个生命周期中都固定为5。