I have a login screen. After user fill up credential, I want to verify it then start a new root view so user won't be able to navigate back to the login view. I currently have
Button(action: {
// launch new root view here
}, label: {Text("Login")}).padding()
Majority of answers I found online are using navigation link which I don't want to. Some other answers suggest to utilize AppDelegate
by UIApplication.shared.delegate
which isn't working for me because I have SceneDelegate
Here is possible alternate approach of how to replace root view completely... using notifications
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
let loginRootViewNotification =
NSNotification.Name("loginRootViewNotification") // declare notification
private var observer: Any? // ... and observer
...
// in place of window creation ...
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
observer = NotificationCenter.default.addObserver(forName: loginRootViewNotification, object: nil, queue: nil, using: { _ in
let anotherRootView = AnotherRootView()
// create another view on notification and replace
window.rootViewController = UIHostingController(rootView: anotherRootView)
})
in your desired place post needed notification
Button(action: {
// launch new root view here
NotificationCenter.default.post(loginRootViewNotification)
}, label: {Text("Login")}).padding()
Another approach with Notifications is to place the observer inside your RootView and check for changes in a variable to decide which View should be presented, here is a very simplified example:
struct RootView: View {
@State var isLoggedIn: Bool = false
var body: some View {
Group {
VStack{
if isLoggedIn {
Text("View B")
Button(action: {
NotificationCenter.default.post(name: NSNotification.Name("changeLogin"), object: nil)
}) {
Text("Logout")
}
} else {
Text("View A")
Button(action: {
NotificationCenter.default.post(name: NSNotification.Name("changeLogin"), object: nil)
}) {
Text("Login")
}
}
}
}.onAppear {
NotificationCenter.default.addObserver(forName: NSNotification.Name("changeLogin"), object: nil, queue: .main) { (_) in
self.isLoggedIn.toggle()
}
}
}
And load RootView in your rootViewController as usual.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = RootView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With