Ios SwiftUI:如何以编程方式更改rootview控制器

Ios SwiftUI:如何以编程方式更改rootview控制器,ios,swift,swiftui,Ios,Swift,Swiftui,我试图在用户注销后将rootview控制器更改为其他屏幕 if let window = UIApplication.shared.windows.first { window.rootViewController = UIHostingController(rootView: SignInView()) window.endEditing(true) window.makeKeyAndVisible() } 这就是我目前所拥有

我试图在用户注销后将rootview控制器更改为其他屏幕

    if let window = UIApplication.shared.windows.first {
        window.rootViewController = UIHostingController(rootView: SignInView())
        window.endEditing(true)

        window.makeKeyAndVisible()
    }

这就是我目前所拥有的。它会导航到不同的视图,但会使新视图上的按钮不可用。是否有更好的方法更改rootview或我遗漏了什么?

如果您在项目中使用的是SceneDelegate.swift文件,请尝试这种方法

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }

        // Instantiate UIWindow with scene
        let window = UIWindow(windowScene: scene)
        // Assign window to SceneDelegate window property
        self.window = window
        // Set initial view controller from Your storyboard as root view controller of UIWindow
        self.window?.rootViewController = UIStoryboard(name: "Your StoryBoard Name", bundle: nil).instantiateInitialViewController()
        // Present window to screen
        self.window?.makeKeyAndVisible()
    }
如果您没有使用ScanDelegate.swift并使用AppDelegate.swift,请尝试这种方法

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }

        // Instantiate UIWindow with scene
        let window = UIWindow(windowScene: scene)
        // Assign window to SceneDelegate window property
        self.window = window
        // Set initial view controller from Your storyboard as root view controller of UIWindow
        self.window?.rootViewController = UIStoryboard(name: "Your StoryBoard Name", bundle: nil).instantiateInitialViewController()
        // Present window to screen
        self.window?.makeKeyAndVisible()
    }
没有InitalViewController:

func logOut {        
    let storyboard = UIStoryboard(name: "Your StoryBoard", bundle: nil)
    if let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController,
        let loginvc = storyboard.instantiateViewController(withIdentifier: "Your Selected ViewController") as? YourSelectedViewController {
        
        navigationController.viewControllers = [loginvc]
        AppDelegate.getAppDelegate().window?.rootViewController = navigationController
        
    }
}
func logOut() {
        let storyboard = UIStoryboard(name: "Your StoryBoard", bundle: nil)
        let navigationController = storyboard.instantiateInitialViewController()
        AppDelegate.getAppDelegate().window?.rootViewController = navigationController
    }
使用InitalViewController:

func logOut {        
    let storyboard = UIStoryboard(name: "Your StoryBoard", bundle: nil)
    if let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController,
        let loginvc = storyboard.instantiateViewController(withIdentifier: "Your Selected ViewController") as? YourSelectedViewController {
        
        navigationController.viewControllers = [loginvc]
        AppDelegate.getAppDelegate().window?.rootViewController = navigationController
        
    }
}
func logOut() {
        let storyboard = UIStoryboard(name: "Your StoryBoard", bundle: nil)
        let navigationController = storyboard.instantiateInitialViewController()
        AppDelegate.getAppDelegate().window?.rootViewController = navigationController
    }
分机:

extension AppDelegate {
    
    class func getAppDelegate() -> AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
    
}

我的方法是创建一个可观察的对象来协调各种应用程序视图之间的导航。下面是一个简单的示例,让您了解:

//Your app views
enum AppViews {
    case LoginView
    case MainAppView
}

//Class that conforms to the ObservableObject protocol and publishes the viewId property.
//Basically your navigation will react to viewId changes

class ShowingView: ObservableObject {
    
    init(showingView: AppViews) {
        self.viewId = showingView
    }
    
    @Published var viewId : AppViews
}

//The current root view of your app is observing changes of the ShowingView class and switch between your app views
struct AppRootView: View {
    
    @ObservedObject var showingView: ShowingView
    
    var body: some View {
        Group {
            if showingView.viewId == .LoginView {
                TermsAndConditionsView()
                    .environmentObject(showingView)
            }
            else {
                MainAppView()
                    .environmentObject(showingView)
            }
        }
    }
}
请注意,您可以将
showingView
作为环境对象传递给视图,并在需要时使用它切换到另一个视图。在您的情况下,当用户注销时切换到另一个屏幕

例如,在场景代理中,您可以在登录和主视图之间切换,如下所示

var appStartView: AppViews

let isloggedIn = UserDefaults.standard.bool(forKey: "IsLoggedIn")

if isLoggedIn == false {
    appStartView = .LoginView
}
else {
    appStartView = .MainAppView
}

let contentView = AppRootView(showingView: ShowingView(showingView: appStartView))

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: contentView)
    self.window = window
    window.makeKeyAndVisible()
}
要在
MainAppView
LoginView
之间切换,只需修改environmentObject
showingView

self.showingView.viewId = AppViews.LoginView

我希望它能帮助您朝着正确的方向前进

该应用程序在SwiftUI中,因此我不使用UI ToryBoardDoes用户默认值的工作方式与状态类似?就像它发生变化一样,它会重新呈现视图吗?用户默认值用于本地持久性。您可以存储首选密钥的值,并在整个应用程序中检索它们。在本例中,在SceneDelegate中,当应用程序开始能够检查用户以前是否登录时,我们只读取“IsLoggedIn”的值。如果在其他地方更改“IsLoggedIn”的值,则不会导致应用程序实时切换视图。只有下一次你的应用程序才会启动。明白了。因此,我有一个注销按钮,一旦用户单击该按钮,我想返回LoginView()。因此,这种方法不适用于这种情况,对吗?如果您按照我的示例,当用户单击注销时,您可以修改viewId的值,如我的回答结尾所述:self.showingView.viewId=AppViews.LoginView。这将把LoginView设置为应用程序的根视图。我建议查看Paul Hudson的这篇文章:他的内容是学习SwiftUI的绝佳资源。如果你认为有帮助,请接受我的回答=)