Ios 防止SwiftUI重置@State
我常常不理解SwiftUI何时重置视图的状态(即所有标记为@state的视图)。例如,请看下面的示例:Ios 防止SwiftUI重置@State,ios,swift,swiftui,Ios,Swift,Swiftui,我常常不理解SwiftUI何时重置视图的状态(即所有标记为@state的视图)。例如,请看下面的示例: import SwiftUI struct ContentView: View { @State private var isView1Active = true let view1 = View1() let view2 = View2() var body: some View { VStack { if isVi
import SwiftUI
struct ContentView: View {
@State private var isView1Active = true
let view1 = View1()
let view2 = View2()
var body: some View {
VStack {
if isView1Active {
view1
} else {
view2
}
Button(action: {
self.isView1Active.toggle()
}, label: {
Text("TAP")
})
}
}
}
struct View1: View {
@State private var text = ""
var body: some View {
TextField("View1: type something...", text: $text)
}
}
struct View2: View {
@State private var text = ""
var body: some View {
TextField("View2: type something...", text: $text)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
我希望这两个TextField
保留它们的内容,但如果运行此示例,会出现一些奇怪的行为:
- 如果在预览中运行示例,则只有
视图1
内容仍然存在:文本字段
- 相反,如果您在模拟器上运行示例(或在实际设备上运行),则第一个文本字段内容和第二个文本字段内容都不会保留:
那么,这里发生了什么?有没有办法告诉SwiftUI不要为视图重置@State?谢谢。问题是每次更改
isView1Active
时都会重新创建View1
和View2
(因为它使用的是@State
重新加载ContentView
的主体)
解决方案是在ContentView
中保留TextField
的文本属性,如下所示,并使用@Binding
:
struct ContentView: View {
@State private var isView1Active = true
@State private var view1Text = ""
@State private var view2Text = ""
var body: some View {
VStack {
if isView1Active {
View1(text: $view1Text)
} else {
View2(text: $view2Text)
}
Button(action: {
self.isView1Active.toggle()
}, label: {
Text("TAP")
})
}
}
}
struct View1: View {
@Binding var text: String
var body: some View {
TextField("View1: type something...", text: $text)
}
}
struct View2: View {
@Binding var text: String
var body: some View {
TextField("View2: type something...", text: $text)
}
}
在行动中显示:
它
view1
和view2
是完全独立和封闭的,就像没有contextmenu
或sheet
一样,您可以使用ZStack
和opacity
组合
var body: some View {
VStack {
ZStack{
if isView1Active {
view1.opacity(1)
view2.opacity(0)
} else {
view1.opacity(0)
view2.opacity(1)
}}
Button(action: {
self.isView1Active.toggle()
}, label: {
Text("TAP")
})
}
}
对于持久性,请使用外部视图模型(例如,ObservableObject)Hi@Asperi,谢谢。我知道使用ObserveObject是可行的,我很可能会这么做(即使我真的很想理解为什么SwiftUI会重置问题示例中的(at)状态)。我认为关于(at)状态管理,我们这里缺少了一些东西。
@State
只有在视图层次结构中查看时才有效。从@State
的角度来看,您创建View1
和View2
的方式无效,因此您要观察您观察到的问题。实际上,如果将View1
&View2
直接放置在使用View1
&View2
变量的位置,您也会观察到同样的情况,因为@State
仅在视图处于视图层次结构时才起作用。好吧,看来我的问题的实际答案是“@State
只有在视图内部视图层次结构中才有效”,这很令人伤心,因为它有一些重要的含义。嗨,乔治,谢谢你。不幸的是,你说的是错的。在我的示例中,View1
和View2
不是每次都重新创建的,因为它们是主视图的let
属性(您可以通过实现它们的init()
方法轻松地对其进行测试。您将看到只调用了一次)。这正是我在问题中提出的问题。尽管视图与视图完全相同(未重新创建),但@State会以某种方式重置。SwiftUI何时重置@State变量?为什么?有办法控制它吗?@superpuccio我明白你的意思,我不知道为什么。但这看起来还是解决了你的问题。@superpuccio,George_E有正确的答案。@状态变量不会在呈现之间持久化。因此,即使您的内存中可能有@State,当视图从视图堆栈中移除时,这些状态变量也会重置。您必须使用@Binding。