I would like to show a ProgressView when the Button is pressed and the user.showLoginProgress property is set, which is declared as published. However, the new value of the property does not seem to trigger the LoginView to refresh, so the ProgressView does not show up:
struct LoginView: View {
@EnvironmentObject var user : User
var body: some View {
VStack{
Button("Login", action: {
user.credentials.showLoginProgress=true // @Published
})
if user.credentials.showLoginProgress{
ProgressView() // never shows up
}
}
}
}
The user is global:
var user : User = User()
@main
struct app1App: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
MainView().environmentObject(user)
}
}
}
and is defined as:
class User : ObservableObject{
@Published var credentials = Login()
}
while the credentials is:
class Login : ObservableObject {
@Published var showLoginProgress : Bool = false
}
Could anyone point out what's wrong with my code?
CodePudding user response:
Try using something like this approach, to re-structure your User
and Login
, where
there is only one ObservableObject
and the login functions are in it.
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@StateObject var manager = UserManager()
var body: some View {
LoginView().environmentObject(manager)
}
}
struct LoginView: View {
@EnvironmentObject var manager: UserManager
var body: some View {
VStack {
if manager.user.isAuthorised {
Text(manager.user.name " is logged in")
}
Button("Login", action: {
manager.doLogin()
})
if manager.showLoginProgress {
ProgressView()
}
}
}
}
class UserManager: ObservableObject {
@Published var user = User()
@Published var showLoginProgress = false
@Published var someOtherVar = ""
func doLogin() {
showLoginProgress = true
// ...
// simulated login
DispatchQueue.main.asyncAfter(deadline: .now() 2) {
self.user.name = "Mickey Mouse"
self.user.isAuthorised = true
self.showLoginProgress = false
}
}
}
struct User: Identifiable, Hashable {
let id = UUID()
var name = ""
var isAuthorised = false
// var credentials: Credentials
// ....
}