Reputation: 126
I'd appreciate any help with this, I'm just a beginner so I'm not sure if I'm misunderstanding, or have the implementation wrong or if this is a bug.
I'm trying to have my MacOS app segue to the main screen after a successful login. I have an appState to share state with the rest of the app. The AppState is a class conforming to Observable object and I added an observer to print whenever the isLoggedIn property changes:
class AppState : ObservableObject {
@Published var isLoggedIn = false {
didSet {
print("AppState isLoggedin: \(isLoggedIn)")
}
}
}
I also have a MasterView struct to deal with changing the main view.
struct MasterView: View {
@ObservedObject var appState: AppState = AppState()
var body: some View {
return Group {
if appState.isLoggedIn {
NavView()
} else {
LoginView()
}
}.frame(width: 1200, height: 800)
}
}
I have a bunch of code to handle doing the login which I won't post for the sake of brevity, suffice to say that it works, isLoggedIn is set to true and prints to the console after a successful login. The issue is that the view never updates to reflect this so I'm still stuck on the login screen.
Any help is greatly appreciated, I've spent more time on this than I care to admit. Thanks!
Update: I remember having trouble with @EnvironmentObject and so I switched to @ObservableObject and @Published. After re-implementing @EnvironmentObject I now remember why: I have a networking class which causes a crash as it is not an ancestor view. Per Paul Hudson's comment, "Note: Environment objects must be supplied by an ancestor view – if SwiftUI can’t find an environment object of the correct type you’ll get a crash. This applies for previews too, so be careful."
Upvotes: 1
Views: 3203
Reputation: 126
I figured it out, working code below.
AppState:
final class AppState : ObservableObject {
@Published var isLoggedIn = false {
didSet {
print("AppState isLoggedIn: \(isLoggedIn)")
}
}
}
Content View :
struct ContentView: View {
@ObservedObject var appState: AppState
var body: some View {
return Group {
if appState.isLoggedIn {
MainView(appState: appState)
} else {
LoginView(appState: appState)
}
}.frame(maxWidth: 1200, maxHeight: 800)
}
}
Login View:
struct LoginView: View {
@ObservedObject var appState: AppState
var body: some View {
Button(action: {
withAnimation {
self.appState.isLoggedIn.toggle()
}
}) {
Text("Go to Main View")
}.padding()
}
}
Finally, Main View:
struct MainView: View {
@ObservedObject var appState: AppState
var body: some View {
Button(action: {
withAnimation {
self.appState.isLoggedIn.toggle()
}
}) {
Text("Back To Login View")
}.padding()
}
}
Upvotes: 2