防止 SwiftUI 重置 @State

sup*_*cio 5 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 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这两个TextField保留他们的内容,但是如果你运行这个例子,会发生一些奇怪的行为:

  • 如果您在预览上运行示例,则仅View1 TextField内容仍然存在:

在此处输入图片说明

  • 相反,如果您在模拟器(或实际设备)上运行该示例,则第一个文本字段内容和第二个文本字段内容均不存在:

在此处输入图片说明

那么,这里发生了什么?有没有办法告诉 SwiftUI 不要为视图重置 @State?谢谢。

Geo*_*e_E 4

问题是View1View2每次更改时都会重新创建isView1Active(因为它正在使用@State它重新加载 的主体ContentView)。

解决方案是保留 s 的文本属性,TextField如下ContentView所示并使用@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)
    }
}
Run Code Online (Sandbox Code Playgroud)

行动中显示:

动图

  • 嗨乔治,谢谢你。不幸的是你所说的是错误的。在我的示例中,“View1”和“View2”不会每次都重新创建,因为它们是主视图的“let”属性(您可以通过实现它们的“init()”方法轻松测试它。您会看到它只是被调用一次)。而这正是我在提问中提出的问题。尽管视图与视图完全相同(未重新创建),@State 仍以某种方式重置。SwiftUI 何时重置 @State var?为什么?有办法控制吗? (3认同)