Search code examples
swiftglobal-variablesswiftuistate

Is there a way to have a global variable between a SwiftUI view and classes indirectly related to it?


I am working on a MacOS Swift project (with SwiftUI), and I am having trouble with updating a text label as an event happens.

struct ContentView: View {
    @State var now = globalString.stringy
    var body: some View {
        VStack {
            Text(now)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }.onAppear {
             k.start()

        }

    }

}

struct globalString {
    static var stringy = ""
    static var temperature = 0.0
}

The variable now above refers a global variable in a struct that is being changed while the program is running (in a different class that is not referred to in this code), but the changes to the variable will not show up in the text label.

How can I make a variable that is shared between this view and that class, while still having my view update when there is a change in the variable? The changes made to the variable are in a separate file.

I tried using an observable object and an environment object but neither seemed to work.

If anyone could help, I would greatly appreciate it. Thanks!


Solution

  • To make changes in a SwiftUI view below iOS 17, as it is a static element because of its struct declaration, your object GlobalString must conform to a StateObject to be able to make changes in real-time to a view, and its variables must conform to @Published.

    As for SwiftUI view for iOS 17+, you can use the @Observable macro and declare your object as a @State value only.

    iOS 17-

    class GlobalString: ObservableObject {
      @Published var stringy = ""
      @Published var temperature = 0.0
    }
    
    struct ContentView: View {
    
      @StateObject var globalString = GlobalString()
    
      var body: some View {
        VStack {
          Text(globalString.stringy)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .onAppear { k.start() }
      }
    }
    

    iOS 17+

    import Observation
    
    @Observable class GlobalString {
      var stringy = ""
      var temperature = 0.0
    }
    
    struct ContentView: View {
    
      @State var globalString = GlobalString()
    
      var body: some View {
        VStack {
          Text(globalString.stringy)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .onAppear { k.start() }
      }
    }