繁体   English   中英

使用@State 变量不适用于从子视图更改 Body 中的视图 state

[英]Using @State variable does not work for changing view state in Body from child view

假设在我的 iOS SwiftUI 应用程序中有一个简单的 ContentView,里面有两个视图。

对 ContentView 的引用可用于代码的其他部分。

用户想要从那里确定显示两个视图中的哪一个,即一个、一个、一个或两个。

该代码类似于

contentViewReference.setView1Visible(view1Visible:true) //or false

这是内容视图

struct ViewsState
{
    var view1Visible:Bool
    var view2Visible:Bool
    init(view1Visible:Bool,view2Visible:Bool)
       {
          self.view1Visible=view1Visible
          self.view2Visible=view2Visible
       }
 }

struct ContentView: View 
{ 
    @State private var viewsState:ViewsState=ViewsState(view1Visible:true,view2Visible:false)

    
    public func setView1Visible(view1Visible:Bool)
        {
          viewsState.view1Visible=view1Visible
        }

    public func setView2Visible(view2Visible:Bool)
        {
          viewsState.view2Visible=view2Visible
        }

    var body: some View 
    {
        if (viewsState.view1Visible) {View1}
        if (viewsState.view1Visible) {View2}
    }
}

但是视图的可见性永远不会改变,为什么?

我认为我不需要绑定,因为 state“真相”在 ContentView 内部,但它是通过公共功能分配的。

没有父视图,切换代码确实位于属于 View1 的菜单内。

但是打电话的时候

setView1Visible(view1Visible:false)

例如,没有效果,View1 不会隐藏。

这只是一小段代码。 真正的 ContentView 稍微复杂一些,但问题没有改变。

@P5music,没有足够的代码来复制您的问题并进行适当的调查。 我也不知道你是怎么得到的:

   contentViewReference.setView1Visible(view1Visible:true) 

以下是关于您的代码的一些观察。

    @State private var viewsState:ViewsState(view1Visible:true,view2Visible:false)

应该

    @State var viewsState = ViewsState(view1Visible:true,view2Visible:false)

你也可能想要:

    var body: some View 
{
    if (viewsState.view1Visible) {View1}
    if (viewsState.view2Visible) {View2}  // <--- here 
}

此外,“...确定显示两个视图中的哪一个”,这意味着每次将“view1Visible”设置为某个值时,同时还需要将“view2Visible”设置为相反的值。

class ViewsState: ObservableObject
{
    @Published var view1Visible:Bool
    @Published var view2Visible:Bool
    init(view1Visible:Bool,view2Visible:Bool)
    {
        self.view1Visible=view1Visible
        self.view2Visible=view2Visible
    }
    public func setView1Visible(view1Visible:Bool)
    {
        self.view1Visible = view1Visible
        view2Visible = !view1Visible
    }
    
    public func setView2Visible(view2Visible:Bool)
    {
        self.view2Visible = view2Visible
        view1Visible = !view2Visible
    }
}

struct ViewStateView: View {
    @StateObject private var viewsState: ViewsState = ViewsState(view1Visible:true,view2Visible:false)

    var body: some View
    {
        VStack{
            if (viewsState.view1Visible) {Text("View1")}
            if (viewsState.view2Visible) {Text("View2")}
            SomeOtherView().environmentObject(viewsState)
        }
    }
}
struct SomeOtherView: View {
    @EnvironmentObject var viewsState: ViewsState
    var body: some View
    {
        VStack{
            Text("SomeOtherView")
            Button("change state view 1", action: {
                viewsState.setView1Visible(view1Visible:false)
            })
            Button("change state view 2", action: {
                viewsState.setView2Visible(view2Visible:false)
            })
        }
        
    }
}
struct ViewStateView_Previews: PreviewProvider {
    static var previews: some View {
        ViewStateView()
    }

假设您的“contentViewReference.setView1Visible(view1Visible:true)”有效,则以下测试代码似乎有效:

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ViewsState{
    var view1Visible:Bool
    var view2Visible:Bool
    init(view1Visible:Bool, view2Visible:Bool){
        self.view1Visible = view1Visible
        self.view2Visible = view2Visible
    }
}

struct ContentView: View {
    @State var viewsState = ViewsState(view1Visible:true, view2Visible:false)
    
    public func setView1Visible(view1Visible:Bool){
        viewsState.view1Visible = view1Visible
        viewsState.view2Visible = !view1Visible
    }
    
    public func setView2Visible(view2Visible:Bool){
        viewsState.view2Visible = view2Visible
        viewsState.view1Visible = !view2Visible
    }
    
    var body: some View {
        VStack {
            Button("change view") {
                if viewsState.view1Visible {
                    setView1Visible(view1Visible: false)
                } else {
                    setView1Visible(view1Visible: true)
                }
            }
            if (viewsState.view1Visible) {View1()}
            if (viewsState.view2Visible) {View2()}
        }
    }
}

struct View1: View {
    var body: some View {
        Text("View1")
    }
}

struct View2: View {
    var body: some View {
        Text("View2")
    }
}

暂无
暂无

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

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