TL;DR
看来 ContentView
下文评估了该机构的 if
声明前 init
已经跑了。是有比赛条件,还是我的心理模型出了问题?
点赞
向Asperi致敬,是他提供了以下信息 状态初始化器等价物 解决了今天的问题。
编码
为什么 ContentView
显示 "dummy is nil"?似乎有什么东西被关闭了 之前 初始化器设置 dummy
. 第二个赋值是怎么解决的?
class Dummy { }
struct ContentView: View {
@State private var dummy : Dummy?
init() {
print("Init") // In either case, is printed before "Body"
// Using this assignment, "dummy is nil" shows on screen.
self.dummy = Dummy()
// Using this, "dummy is non-nil" shows on screen.
// From https://stackoverflow.com/questions/61650040/swiftui-initializer-apparent-circularity
// self._dummy = State(initialValue: Dummy())
}
var body: some View {
print("Body")
return ZStack {
if dummy == nil { // Decision seems to be taken
Text("dummy is nil" ) // before init() has finished.
} else {
Text("dummy is non-nil")
}
}
}
}
一致认为,这是一个看起来像bug的功能。
有用的讨论 在Swift论坛。也在这里. 重点内容(为清晰起见进行了编辑)包括:。
很好的理由不这样做摆在首位。
你不应该变异期间 View
init中,因为那会在body
父视图的调用
@State
SwiftUI中的变量不应该从你通过初始化器传递下来的数据中进行初始化;因为模型是在视图之外进行维护的,所以不能保证该值真的会被使用。
不要尝试覆盖 @State
的初始值,在 init
. 它只会在第一次创建视图时起作用(重要的是:不是值的初始化),而且只有当视图树中的那个视图被重新创建后,才会被一个相同类型但内部ID不同的不同视图所取代。
这是一个误区 "的立场(与我的立场接近)。
_value
解释如何和为什么。
价值 @State
将始终以你传入的值进行初始化。init
,这就是简单的Swift。然而在下一步之前 body
调用SwiftUI会调用update方法并重新注入一个值,如果之前有一个值,会覆盖你的init值。
这不是一个错误! :man_facepalming: 它的工作原理和预期的一样。... @State
属性包装器给视图增加了一种可能的突变方式,这也是为了让视图私有化,而不是从父节点初始化,等等。
这是试点错误(可能是真的)。