繁体   English   中英

防止 SwiftUI 重置 @State

[英]Prevent SwiftUI from resetting @State

我通常不明白 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()
    }
}

我希望两个TextField保留其内容,但是如果您运行此示例,则会发生一些奇怪的行为:

  • 如果您在预览中运行该示例,则只有View1 TextField内容仍然存在:

在此处输入图片说明

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

在此处输入图片说明

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

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

一种解决方案是将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)
    }
}

显示在行动中:

动图

view1view2是完全独立和封闭的,就像没有contextmenusheet ,您可以使用ZStackopacity组合。

 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")
        })
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM