Global Variables in SwiftUI

I am trying to declare a global variable, which to my knowledge can be declared in any file as such:

struct globalVariable{
    public var usrName = ""
}

This is declared in my root View. I want to update that variable when a user logs into the application, this global variable will be updated with the log in user's user name. I want to do the update in the following function in an authentication file.

func login(username: String, password: String) {
      
    self.isAuthenticating = true
      
      //Open database for validation
      let userDB = UserDatabase().createDB()
      
      <------ Update the global variable to the passed in userName
      
      
      //Open Database for filtering
      //let photoDB = DbHelper().getPictures(usrName: username)
      
      if checkUser(db: userDB,un: username,pw: password) == true {
          print("Login Succeeded")
          // emulate a short delay when authenticating
          DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.isAuthenticating = false
            self.needsAuthentication = false
          }
      }else {
         print("Login Failed")
      }
  }

After updating the file, I want to pass this value into a function that is called in my content view as such:

import SwiftUI



struct ContentView: View {
    
    @EnvironmentObject var authenticator: Authenticator
    
    @State private var rating: Int = 0
    
    
    var pictureURL = DbHelper().getPictures()  <-- Pass in global Variable
    
    
    var body: some View {
        List(pictureURL, id: \.self) { photo in
            VStack{
                if #available(iOS 15.0, *) {
                    AsyncImage(url: URL(string: photo), scale: 10.0)
                } else {
                    // Fallback on earlier versions
                }
                RatingView(rating: $rating)
            }
        }
        Button("Logout") {
            authenticator.logout()
        }
    }
}


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

How would I go about solving this with global variables?

Upvotes: 0

Views: 4932

Answers (1)

I would suggest you use dependency injection instead of trying to use a "global" variable.

change

struct globalVariable{
    public var usrName = ""
}

into

class GlobalModel: ObservableObject {
    @Published var usrName = ""
}

Set it in your upper app hierarchy like this:

@StateObject var globalModel = GlobalModel()

and pass it around the views that need it, for example using,

.environmentObject(globalModel)

Upvotes: 2

Related Questions