简体   繁体   English

如何在 SwiftUI 中正确实现一个全局变量

[英]How to properly implement a global variable in SwiftUI

I am going to create a SwiftUI application where I want to be able to swap between 3 modes.我将创建一个 SwiftUI 应用程序,我希望能够在其中切换 3 种模式。 I am trying EnvironmentObject without success.我正在尝试EnvironmentObject但没有成功。 I am able to change the view displayed locally, but from another View (in the end will be a class) I get a我能够更改本地显示的视图,但是从另一个View (最后将是一个类)我得到一个

fatal error: No ObservableObject of type DisplayView found. A View.environmentObject(_:) for DisplayView may be missing as an ancestor of this view.

Here is my code.这是我的代码。 The first line of the ContentView if/else fails. ContentView 的第一行 if/else 失败。

enum ViewMode {
    case Connect, Loading, ModeSelection
}
class DisplayView: ObservableObject {
    @Published var displayMode: ViewMode = .Connect
}

struct ContentView: View {
    @EnvironmentObject var viewMode: DisplayView
    var body: some View {
        VStack {
            if viewMode.displayMode == .Connect {
                ConnectView()
            } else if viewMode.displayMode == .Loading {
                LoadingView()
            } else if viewMode.displayMode == .ModeSelection {
                ModeSelectView()
            } else {
                Text("Error.")
            }
            TestView() //Want this to update the var & change UI.
        }
        .environmentObject(viewMode)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(DisplayView())
    }
}

//FAILS
struct TestView: View {
    @EnvironmentObject var showView: DisplayView
    var body: some View {
        HStack {
            Button("-> load") {
                self.showView.displayMode = .Loading
            }
        }
    }
}

struct ConnectView: View {
    var body: some View {
        Text("Connect...")
    }
}

struct LoadingView: View {
    var body: some View {
        Text("Loading...")
    }
}

struct ModeSelectView: View {
    var body: some View {
        Text("Select Mode")
    }
}

I would like to be able to update DisplayView from anywhere and have the ContentView UI adapt accordingly.我希望能够从任何地方更新DisplayView并相应地调整ContentView UI。 I can update from within ContentView but I want to be able update from anywhere and have my view change.我可以从 ContentView 中更新,但我希望能够从任何地方更新并更改我的视图。

I needed to inject BEFORE - so this fixed things up:我需要先注射 - 所以这解决了问题:

@main
struct fooApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(DisplayView()) //super key!
        }
    }
}

I also tried a Singleton class to store some properties - and thus they are available from anywhere and can be updated anywhere - without having to declare EnvironmentObject.我还尝试了 Singleton class 来存储一些属性——因此它们可以从任何地方获得并且可以在任何地方更新——而无需声明 EnvironmentObject。 It's just another way that can work in different circumstances.这只是可以在不同情况下工作的另一种方式。

class PropContainerModel {
    public var foo = "Hello"
    static let shared = PropContainerModel()
    private override init(){}
}

And then somewhere else然后在别的地方

let thisFoo = PropContainerModel.shared.foo
//
PropContainerModel.shared.foo = "There"

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

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