Swift 为什么可以';我不能在stackView中添加一个子视图,而不使stackView成为惰性变量吗?

Swift 为什么可以';我不能在stackView中添加一个子视图,而不使stackView成为惰性变量吗?,swift,Swift,差不多就是标题;尝试向stackView添加2个标签,同时将其(堆栈视图)设为常量会导致错误 Instance member 'labelOne' cannot be used on type 'ViewController' 然而,使stackView成为一个懒惰的var可以解决这个问题 为什么呢?这是解决这个问题的唯一途径吗?;也就是说,有没有可能让它们成为常量而不出现这个问题 编辑: 代码: 差异与设置这些变量值的时间有关。labelOne和stackView都是ViewControll

差不多就是标题;尝试向stackView添加2个标签,同时将其(堆栈视图)设为常量会导致错误

Instance member 'labelOne' cannot be used on type 'ViewController'
然而,使stackView成为一个懒惰的var可以解决这个问题

为什么呢?这是解决这个问题的唯一途径吗?;也就是说,有没有可能让它们成为常量而不出现这个问题

编辑:

代码:


差异与设置这些变量值的时间有关。
labelOne
stackView
都是ViewController上的实例成员,它们都将获得从闭包(从周围的
{…}()
语法)返回的值

但是,以这种方式声明的“常规”属性将在ViewController初始化后立即运行闭包,而惰性属性将等待运行闭包,直到第一次访问该属性—以及在初始化之后。它们之间的实际区别是,
self
可用于延迟运行的闭包,但
self
不可用于初始化时运行的闭包。(您要使用的
self
仍在初始化中!)

另一个问题是,在这两个闭包中,您可能看起来都不是在访问
self
!但是,在Swift中,无论何时访问成员属性,它都会隐式使用
self
——因此在第二个闭包中对
labelOne
的引用实际上是对
self.labelOne
,这就是
self
完全初始化的要求。使闭包
lazy
可以让
self
在计算之前做好准备,这样就可以编译代码

这里通常的替代方法是显式初始化
viewDidLoad()
中视图控制器的所有子视图,并将属性本身声明为隐式展开选项(IUO)。这看起来像:

class ViewController: UIViewController {
    var labelOne: UILabel!
    var stackView: UIStackView!

    override func viewDidLoad() {
        super.viewDidLoad()
        labelOne = …
        stackView = …
    }
}
这被称为“两阶段初始化”,并由以下人员隐式推荐:

调用视图控制器的
viewDidLoad
方法。 使用此方法可以添加或删除视图、修改布局约束以及加载视图的数据

你能给我看看吗?
class ViewController: UIViewController {
    var labelOne: UILabel!
    var stackView: UIStackView!

    override func viewDidLoad() {
        super.viewDidLoad()
        labelOne = …
        stackView = …
    }
}