简体   繁体   English

IOS | 无法在应用委托中更改根视图 controller

[英]IOS | Unable to change root view controller in app delegate

I am building an app whose root view controller must be changed if the user is logged in. Say if the user is logged in I must show a tab bar controller as the home screen if the user is not logged in, I must show an Authentication controller.我正在构建一个应用程序,如果用户登录,则必须更改其根视图 controller。假设用户已登录,我必须显示标签栏 controller 作为主屏幕如果用户未登录,我必须显示身份验证controller。 Both my controllers are storyboard controllers.我的两个控制器都是 storyboard 控制器。 Now in my app delegate, I have put the following code现在在我的应用程序委托中,我输入了以下代码

        window = UIWindow(frame: UIScreen.main.bounds)

        if UserDefaults.standard.bool(forKey: Constants.UserDefaultsKeys.isLoggedIn){
            initialViewController = storyboard.instantiateViewController(identifier: Constants.StoryBoards.homeViewController) as! TabController
        }else{
            initialViewController = storyboard.instantiateViewController(identifier: Constants.StoryBoards.authenticationController)
        }
        window?.rootViewController = initialViewController
        window?.makeKeyAndVisible()

As per the code if the user is logged in, TabController must be showed.But it is not being shown.I have tried debugging and TabController 's viewDidLoad is being called but still my authenticationController is being shown and that is probably because authenticationController is set as the initial viewcontroller in the storyboard.根据代码,如果用户已登录,则必须显示TabController 。但未显示。我已尝试调试并且正在调用TabControllerviewDidLoad但仍然显示我的authenticationController ,这可能是因为设置了authenticationController作为 storyboard 中的初始视图控制器。 Can someone help me figure out the issue有人可以帮我解决问题吗

If you are targeting only iOS 13+ , the only change you should need to make is to add one line:如果您只针对iOS 13+ ,您需要做的唯一更改是添加一行:

    window?.rootViewController = initialViewController

    // add this line
    self.window = window

    window?.makeKeyAndVisible()

If you want to support earlier iOS versions, here is a complete SceneDelegate / AppDelegate implementation:如果要支持更早的 iOS 版本,这里有一个完整的 SceneDelegate / AppDelegate 实现:

SceneDelegate.swift SceneDelegate.swift

//
//  SceneDelegate.swift
//  Created by Don Mag on 3/27/20.
//

import UIKit

// entire class is iOS 13+
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        print("Scene Delegate willConnectTo", UserDefaults.standard.bool(forKey: "isLoggedIn"))

        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window.windowScene = windowScene

        if UserDefaults.standard.bool(forKey: "isLoggedIn") {
            guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeVC") as? TabController else {
                fatalError("Could not instantiate HomeVC!")
            }
            window.rootViewController = vc
        } else {
            guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AuthVC") as? AuthViewController else {
                fatalError("Could not instantiate HomeVC!")
            }
            window.rootViewController = vc
        }

        self.window = window

        window.makeKeyAndVisible()
    }

}

AppDelegate.swift AppDelegate.swift

//
//  AppDelegate.swift
//  Created by Don Mag on 3/27/20.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window : UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
            if #available(iOS 13, *) {
                // do only pure app launch stuff, not interface stuff
            } else {

                print("App Delegate didFinishLaunching... isLoggedIn:", UserDefaults.standard.bool(forKey: "isLoggedIn"))

                self.window = UIWindow()

                if UserDefaults.standard.bool(forKey: "isLoggedIn") {
                    guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeVC") as? TabController else {
                        fatalError("Could not instantiate HomeVC!")
                    }
                    window?.rootViewController = vc
                } else {
                    guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AuthVC") as? AuthViewController else {
                        fatalError("Could not instantiate HomeVC!")
                    }
                    window?.rootViewController = vc
                }

                window?.makeKeyAndVisible()

            }
            return true
    }

    // MARK: UISceneSession Lifecycle

    // iOS 13+ only
    @available(iOS 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
    // iOS 13+ only
    @available(iOS 13.0, *)
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    }

}

Here's a way to extend your UIWindow (and access to your rootViewController) into your view controllers to make it easier to change your rootviewcontroller throughout your app:这是一种将您的 UIWindow(并访问您的 rootViewController)扩展到您的视图控制器的方法,以便更轻松地在整个应用程序中更改您的 rootviewcontroller:

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
}

var sceneDelegate: SceneDelegate? {
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
        let delegate = windowScene.delegate as? SceneDelegate else { return nil }
     return delegate
}}
   





extension UIViewController {   
        var window: UIWindow? {
            if #available(iOS 13, *) {
                guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                    let delegate = windowScene.delegate as? SceneDelegate, let window = delegate.window else { return nil }
                       return window
            }
            
            guard let delegate = UIApplication.shared.delegate as? AppDelegate, let window = delegate.window else { return nil }
            return window
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 iOS更改视图控制器来自应用程序委托? - iOS change view controller from the app delegate? 尝试更改根视图控制器时,App Delegate 因 NSException 崩溃 - App Delegate crashes with NSException when trying to change root view controller 在app委托中弹出到根视图控制器 - Pop to root view controller in app delegate iOS(Swift)-投射应用程序委托窗口的根视图控制器可在模拟器中运行,但在手机上加载应用程序时失败 - iOS (Swift) - Casting root view controller of the app delegate's window works in simulator, but fails when app is loaded on phone 服务器调用App Delegate后如何更改根控制器? - How to change root controller after a server call on App Delegate? 视图控制器响应iOS 12中的应用程序委托通知,但不响应iOS 13中的应用委托通知 - View controller responds to app delegate notifications in iOS 12 but not in iOS 13 从 iOS 中的 App Delegate 调用当前视图 controller 中的方法 - Calling method in current view controller from App Delegate in iOS 来自应用程序委托的导航控制器中的iOS切换视图 - iOS switch view in a navigation controller from the app delegate iOS:导航到未直接与应用程序委托连接的视图控制器 - iOS: navigate to a view controller not directly connected from the app delegate MacOS 应用程序无法实例化 SwiftUI 视图作为根视图 controller - MacOS app unable to instantiate SwiftUI view as a root view controller
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM