【问题标题】:when need to switch the rootViewController什么时候需要切换rootViewController
【发布时间】:2022-11-09 22:16:27
【问题描述】:

我一直在做一个 Swift 项目,我有两个视图控制器,登录视图控制器和主视图控制器。当用户启动应用程序时,如果用户未登录,我想显示登录视图控制器,另一方面,如果用户已登录,我想显示主视图控制器。

所以流程会是这样的。

当用户未登录时,显示

  1. 登录视图控制器
  2. 主页视图控制器

    当用户已经登录时,显示

    1. 主页视图控制器

      在场景委托中,我写了

      func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
          guard let scene = (scene as? UIWindowScene) else { return }
      
          window = UIWindow(frame: scene.coordinateSpace.bounds)
          window?.windowScene = scene
          window?.rootViewController = HomeViewController() or LoginViewController() depending on the user's login status
          window?.makeKeyAndVisible()
      }
      

      我想知道是否应该将 HomeViewController 应用为 rootviewcontroller 而不管用户的登录状态如何(并且可能在用户未登录时在 homeVC 上显示 loginVC),或者我应该根据用户的登录状态切换视图控制器。

      那么,这种情况下,切换rootviewcontroller有什么意义呢?为什么切换根视图控制器是(或不重要)?

      当我将视图控制器应用于根视图控制器属性时,我应该考虑什么?

【问题讨论】:

    标签: ios swift xcode rootviewcontroller uiscenedelegate


    【解决方案1】:
    // SceneDelegate.swift
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }
    
        // if user is logged in before
        if let loggedUsername = UserDefaults.standard.string(forKey: "username") {
            window?.rootViewController = HomeViewController()
        } else {
            // if user isn't logged in
            window?.rootViewController = LoginViewController()
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为可能还有其他情况,例如 Root 是一个容器 View Controller 由 HomeVC 和 LoginVC 组成。 例子)

      final class RootVC: UIViewController {
       private let loginVC = LoginVC()
       private let homeVC = HomeVC()
       
       override func viewDidLoad() {
        super.viewDidLoad()
         addChild(homeVC)
         view.addSubview(homeVC.view)
         addChild(loginVC)
         view.addSubview(loginVC.view)
       }
      
       func showVC() {
        if isLogin {
         homeVC.hide()
         loginVC.show()
        } else {
         reverse()
        }
       }
      }
      

      【讨论】:

        【解决方案3】:

        大家好,我有一个想法可以在SceneDelegate 中设置一个 RootViewController。首先,我们需要在SceneDelegate 类中创建方法setViewController 和变量currentScene,请随时参考下面的代码。 根据您的示例 HomeViewController、LoginViewController 有两个不同的视图控制器

        import UIKit
        
        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
          
          var window: UIWindow?
          var currentScene: UIScene?
          
          func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            guard let _ = (scene as? UIWindowScene) else { return }
            currentScene = scene
            if UserDefaults.standard.bool(forKey: "isLoggedIn") == true{
              self.setRootViewController(LoginViewController())
            }else{
              self.setRootViewController(HomeViewController())
            }
          }
          
          func setRootViewController(_ viewController: UIViewController){
            
            guard let scene = (currentScene as? UIWindowScene) else { return }
            
            window = UIWindow(frame: scene.coordinateSpace.bounds)
            window?.windowScene = scene
            window?.rootViewController = viewController
            window?.makeKeyAndVisible()
            
          }
          
        }
        
        class ButtonViewController: UIViewController {
          
          lazy var button: UIButton! = {
            
            let button = UIButton()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.backgroundColor = .darkGray
            button.setTitleColor(.white, for: .normal)
            button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
            button.tag = 1
            button.setTitle("Tap", for: .normal)
            return button
            
          }()
          
          
          override func loadView() {
            super.loadView()
            self.view.backgroundColor = .white
            
            setConstraint()
          }
          
          override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            
          }
          
          func setConstraint(){
            
            self.view.addSubview(self.button)
            
            NSLayoutConstraint.activate([
              
              self.button.heightAnchor.constraint(equalToConstant: 60),
              self.button.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.66),
              self.button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
              self.button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
              
            ])
            
          }
          
          @objc func buttonAction(){  }
          
        }
        
        class HomeViewController: ButtonViewController{
          
          override func loadView() {
            super.loadView()
            self.view.backgroundColor = .red
            self.button.setTitle(String(describing: HomeViewController.self), for: .normal)
          }
          
          override func buttonAction() {
            let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
            sceneDelegate.setRootViewController(LoginViewController())
          }
          
        }
        
        
        class LoginViewController: ButtonViewController{
          
          override func loadView() {
            super.loadView()
            self.view.backgroundColor = .green
            self.button.setTitle(String(describing: LoginViewController.self), for: .normal)
          }
          
          override func buttonAction() {
            let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
            sceneDelegate.setRootViewController(HomeViewController())
          }
          
        }
        

        如果单击按钮视图控制器可以更改为 rootViewController。 输出:

        【讨论】:

        • 感谢您分享您的想法。我实际上需要从视图控制器中引用窗口来切换根视图控制器,所以这真的很有帮助。
        猜你喜欢
        • 2014-04-15
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 2018-12-10
        • 2010-12-29
        • 2017-07-13
        • 2012-08-21
        • 2011-08-18
        相关资源
        最近更新 更多