Change the root view of UIHostingController in SwiftUI

前端 未结 5 911
情歌与酒
情歌与酒 2020-12-03 07:19

For a new SwiftUI iOS app, I do the following in the SceneDelegate

if let windowScene = scene as? UIWindowScene {
    let window =          


        
相关标签:
5条回答
  • 2020-12-03 07:55

    You can make a Router class

    import Foundation
    import UIKit
    import SwiftUI
    
    class Router {
        
        class var window: UIWindow? {
            if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
                if let sceneDelegate = scene.delegate as? SceneDelegate {
                    let window = UIWindow(windowScene: scene)
                    sceneDelegate.window = window
                    window.makeKeyAndVisible()
                    return window
                }
            }
            return nil
        }
        
        static func showMain() {
            window?.rootViewController = UIHostingController(rootView: ContentView())
        }
        
    }
    

    Usage :

    Router.showMain()
    

    And with this you can decide which window you want as your root at any given time.

    0 讨论(0)
  • 2020-12-03 07:58

    Very good answer LuLugaga, updated if you don't want to use @Observablebject so will not keep updating all the time, you can use Subject, as soon as you update token String, RootView will update.

    struct RootView: View {
    
        var loginViewModel: LoginViewModel = LoginViewModel()
    
        @State var tokenString = ""
    
        var body: some View {
            Group {
                tokenString.count > 0 ? AnyView(ContentView(model: playerViewModel)) :  AnyView(LoginView(loginViewModel: loginViewModel))
            }.onReceive(loginViewModel.tokenString) {
                self.tokenString = $0
            }
        }
    }
    
    
    class LoginViewModel {
    
        let tokenString = PassthroughSubject<String, Never>()
    
        var token: String {
            get { return "" }
        set {
            self.tokenString.send(newValue)
        }
    }
    
    0 讨论(0)
  • 2020-12-03 07:59
    let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
    
    if let windowScenedelegate = scene?.delegate as? SceneDelegate {
       let window = UIWindow(windowScene: scene!)
       window.rootViewController = UIHostingController(rootView:ContentView())
       windowScenedelegate.window = window
       window.makeKeyAndVisible()
    }
    

    By using this we can change the rootView in any button click by implementing the above code.

    0 讨论(0)
  • 2020-12-03 08:03

    For some animation while changing the rootview use the below code in sceneDelegate:

        window.rootViewController = UIHostingController(rootView: HomeView())
    
        // A mask of options indicating how you want to perform the animations.
        let options: UIView.AnimationOptions = .transitionCrossDissolve
    
        // The duration of the transition animation, measured in seconds.
        let duration: TimeInterval = 0.3
    
        // Creates a transition animation.
        UIView.transition(with: window, duration: duration, options: options, animations: {}, completion:
        { completed in
            // maybe do something on completion here
        })
    
    0 讨论(0)
  • 2020-12-03 08:11

    Declare an AppRootView, something like this:

    struct AppRootView: View {
    
        @ObservedObject private var auth: Auth
        var body: some View {
            Group {
                if auth.token != nil {
                    MainTabbedView()
                } else {
                    StartRegistrationView()
                }
            }
        }
    }
    

    and then in SceneDelegate set it as the root view:

    window.rootViewController = UIHostingController(rootView: AppRootView(auth: $auth))

    You have to bind your view to your Auth() either by passing it in as I did above or by setting it on your environment. The beauty of SwiftUI is that as soon as the token is not nil, the view will redraw and your user will find them selves in MainTabbedView.

    0 讨论(0)
提交回复
热议问题