TL; DR
似乎ContentView
会在if
运行之前评估主体的init
语句。是否存在比赛条件,或者我的心理模型是否混乱?
荣誉
向阿斯佩里大喊大叫,阿斯佩里提供了state-initializer equivalent来解决当今的问题。
代码
为什么ContentView
显示“虚拟为零”?似乎在初始化器设置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")
}
}
}
}
答案 0 :(得分:0)
共识是它是一个看起来像错误的功能。
Helpful discussion在Swift论坛中。 Also here。亮点(为清晰起见进行了编辑)包括:
首先没有这样做的充分理由:
您不应该在View
初始化期间进行突变,因为它会在
body
调用父视图
@State
变量不应从通过初始化程序传递的数据中初始化;由于模型是在视图外部维护的,因此无法保证该值将被真正使用。
请勿尝试在@State
期间覆盖init
的初始值。在第一次创建视图时(仅重要:不是值初始化),并且仅在视图树中的该视图被重新创建/替换为相同类型但内部具有不同ID的其他视图时,它才会工作一次。
“这是功能失常的”位置(接近我的位置):
_value
说明方式和原因:
@State
中的值将始终使用您在init
中传递的值进行初始化,这是简单的Swift。但是,在下一个body
调用之前,SwiftUI将调用update方法并在之前的值覆盖了init值的情况下重新向其中注入一个值。
这不是错误! :man_facepalming:它按预期/广告方式工作。 ... @State
属性包装器为视图添加了一种可能的突变方式,这也意味着该视图是私有的,而不是从父级初始化的,等等。
这是试点错误(可能是真的):