【发布时间】:2020-05-07 15:25:31
【问题描述】:
TL;DR
似乎下面的ContentView 在init 运行之前评估了主体的if 语句。是否存在竞争条件,或者我的心智模型有问题?
荣誉
向 Asperi 致敬,他提供了解决当今问题的 state-initializer equivalent。
代码
为什么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")
}
}
}
}
【问题讨论】:
-
这只是
@State属性包装器的本质...接受它:) -
我没有太多选择......但仍然很奇怪。这出现在一个商业应用程序中,而不仅仅是一个玩具示例。我尝试了[长长的事情清单],就在今天早上(在其他地方)看到了你的答案,并认为“这不应该有所作为......但我会试试看。”
-
不是
before init() has finished。只是self.dummy = Dummy()什么都不做,跳过了。如果您需要初始化状态,那么您必须直接在属性声明中或通过self._dummy在初始化中进行,或者在视图已经存在时进行更改,例如在.onAppear及更高版本中。 -
我不太明白你所说的“什么都不做”是什么意思。编译器是否有权优化状态分配?在我的例子中,假人是
PlayerViewModel的一个实例,你在两个月前对它进行了很有帮助的解释。我确实尝试将其设置为.onAppear,但那时它已经不是零了。它只是没有出现在屏幕上,因为声明式布局中的if子句已将其排除在外。 -
我在
@Statevars 中看到了在初始化程序中设置的图像的相同问题(具有相同的修复)。 IE。在View首次出现时,没有图像。在我看来,它真的像依赖管理中的竞争条件。
标签: initialization swiftui race-condition property-wrapper