【问题标题】:How to set a new root view controller如何设置新的根视图控制器
【发布时间】:2016-01-27 05:39:55
【问题描述】:

我想知道是否可以设置一个新的根VC?

我的应用使用 uinavigation 控制器进行初始化,该控制器具有作为根 VC 的表视图。

然后从表格视图中,我正在运行另一个登录窗口(以模态方式显示)如果您随后登录,您最终会进入 red VC/帐户页面。我现在要做的是将红色 VC 设置为应用程序的新根 VC,并删除所有底层 VC。这样我就可以显示菜单按钮/图标而不是“返回”按钮

我找到了这个,但我不明白如何使用它:

let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
        let yourViewController: ViewController = storyboard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as! ViewController

        let navigationController = self.window?.rootViewController as! UINavigationController
        navigationController.setViewControllers([yourViewController], animated: true)

但我无法让它工作。那么是否可以让图中红色的vc作为新的根VC呢?

【问题讨论】:

    标签: swift uinavigationcontroller storyboard


    【解决方案1】:

    斯威夫特 4.2

    也许你应该试试这个

    let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
    let redViewController = mainStoryBoard.instantiateViewController(withIdentifier: "respectiveIdentifier") as! ViewController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.window?.rootViewController = redViewController
    

    【讨论】:

    • 好吧...它不会崩溃。但对我来说,这里什么都没有发生。不会加载新视图
    • 我的问题是新的视图控制器替换了旧的。但是仍然保留视图控制器堆栈。不知道那些视图控制器堆栈来自哪里。
    • 使用SceneDelegate的人请参考stackoverflow.com/questions/56588843/…
    【解决方案2】:

    Swift 4、5、5.1

    let story = UIStoryboard(name: "Main", bundle:nil)
    let vc = story.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
    UIApplication.shared.windows.first?.rootViewController = vc
    UIApplication.shared.windows.first?.makeKeyAndVisible()
    

    【讨论】:

    • 非常感谢。 !!这对我有很大帮助。
    • makeKeyAndVisible 可以解决问题!谢谢
    • 非常感谢
    【解决方案3】:

    Swift 3 更新:-

    let testController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "testController") as! TestController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.window?.rootViewController = testController
    

    【讨论】:

    • 为我工作谢谢
    • 这不会从下面删除以前的视图...
    【解决方案4】:

    斯威夫特 4 答案

    let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
    let nextViewController = storyBoard.instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
    let navigationController = UINavigationController(rootViewController: nextViewController)            
    let appdelegate = UIApplication.shared.delegate as! AppDelegate
    appdelegate.window!.rootViewController = navigationController
    

    【讨论】:

    • 如何用导航栏实例化根视图控制器...我不明白
    • 在xcode 11中做什么。appdelegate中没有window属性
    【解决方案5】:

    UINavigationController 有一个 viewControllers 属性,它是一个 NSArray,你可以用你自己的视图控制器的 NSArray 替换它。

    这可以通过下面的示例代码来完成。

    let newViewController = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewControllerollerID") as! YourViewController
    let customViewControllersArray : NSArray = [newViewController]
    navigationController?.viewControllers = customViewControllersArray as! [UIViewController]
    

    如果你想展示这个新的根视图控制器,你可以调用 UINavigationController 的 popToRootViewController() 方法。

    navigationController?.popToRootViewControllerAnimated(true)
    

    【讨论】:

      【解决方案6】:

      为了让原始问题中的代码 sn-p 正常工作,我不得不对第三行进行更改

      let navigationController = self.navigationController!
      

      我在新根视图控制器之前的视图控制器中的@IBAction 中使用此代码。

      使用原始代码时,我收到一条错误消息,指出我的视图控制器没有名为 window 的成员。查看documentation 后,我找不到名为window 的属性。我想知道上面的原始代码块是否打算在UINavigationController 文件中使用。

      这是整个区块。

      let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
      let todayViewController: TodaysFrequencyViewController = storyboard.instantiateViewControllerWithIdentifier("todaysFrequency") as! TodaysFrequencyViewController    
      let navigationController = self.navigationController!
      navigationController.setViewControllers([todayViewControl ler], animated: true)
      

      【讨论】:

        【解决方案7】:

        我想知道是否可以设置一个新的根VC?

        是的,这是可能的。你怎么做取决于上下文......

        我的应用使用 uinavigation 控制器进行初始化,该控制器具有作为根 VC 的表视图。

        实际上有两个东西通常被称为“根视图控制器”:

        • UIWindow 有一个可写的rootViewController 属性。

        • UINavigationController 没有rootViewController 属性,但它确实有一个名为-initWithRootViewController: 的初始化程序。您可以设置导航控制器的“根”视图控制器,方法是设置它的 viewControllers 属性。

        听起来您正在尝试更改窗口的根视图控制器,但您显示的代码仅更改了导航控制器的 viewControllers 属性。尝试直接设置窗口的rootViewController 属性。但是,请理解,如果您采用这种方法,那么导航控制器也会消失。另一方面,如果您想保留导航控制器,请采用您当前的方法。

        但我无法让它工作。那么是否可以让图中红色的vc作为新的根VC呢?

        此处提供更多信息会有所帮助。 “无法正常工作”是什么意思?会发生什么,您预计会发生什么?

        【讨论】:

        • 经过您的解释,我认为我应该更改窗口根目录。但是如果我这样做,我可以添加一个新的 uinavigation 控制器并删除所有旧视图吗?例如 VC 由模态 segue 打开
        • 在故事板中,我还检查了导航控制器上的“是初始 VC”
        • 可以,但是如果您的导航控制器已经是窗口的根视图控制器,并且如果您想要导航控制器并且不需要当前的视图控制器堆栈,那么为什么不保留导航控制器你有? IOW,您当前的方法是合理的——如果它不起作用,您应该提供更多信息。你怎么知道它不起作用? navigationController.viewControllers设置后会显示什么?
        • 我收到错误“MyViewController”没有名为视图的成员。在转换到应该成为新根的新 VC 时,我应该在哪里/如何准确地实现代码?
        • 每个视图控制器都有一个view 属性,因此如果您收到该消息,则您正在发送消息的对象不是正确的视图控制器。首先确保您的 ViewController 类派生自 UIViewController
        【解决方案8】:

        对于 swift 4.0

        didfinishedlaunchingWithOptions 方法的 AppDelegate.swift 文件中,输入以下代码。

        var window: UIWindow?
        
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            window = UIWindow(frame: UIScreen.main.bounds)
            window?.makeKeyAndVisible()
        
            let rootVC = MainViewController() // your custom viewController. You can instantiate using nib too. UIViewController(nib name, bundle)
        
            let navController = UINavigationController(rootViewController: rootVC) // Integrate navigation controller programmatically if you want
            window?.rootViewController = navController
        
            return true
        }
        

        希望它能正常工作。

        【讨论】:

          【解决方案9】:

          您可以在单击登录按钮时使用此代码:-

          let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
          var vc = mainStoryboard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as ViewController  
          UIApplication.sharedApplication().keyWindow.rootViewController = vc
          

          【讨论】:

            【解决方案10】:

            你可以使用这段代码:

            let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
            
            let customViewControllersArray : NSArray = [newViewController]
            self.navigationController?.viewControllers = customViewControllersArray as! [UIViewController]
            self.navigationController?.pushViewController(newViewController, animated: true)
            

            【讨论】:

            • 您能解释一下为什么您的代码有助于回答 OP 的问题吗?
            • 如果 HomeViewController 是您的根视图控制器,那么您可以使用 pushViewController 将其设置为根视图控制器
            【解决方案11】:

            如果需要给rootViewController设置一些动画,代码如下:

            guard let window = UIApplication.shared.keyWindow else {
                return
            }
            
            guard let rootViewController = window.rootViewController else {
                return
            }
            
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "MainTabbar")
            vc.view.frame = rootViewController.view.frame
            vc.view.layoutIfNeeded()
            
            UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
                window.rootViewController = vc
            }, completion: { completed in
                // maybe do something here
            })
            

            【讨论】:

              【解决方案12】:

              对于 Swift 5 用户,您可以这样做,这绝对适合您。

              var window: UIWindow?
              
              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).
                  manageLoginSession()
                  guard let _ = (scene as? UIWindowScene) else { return }
              }
              
              func manageLoginSession() {
                  guard let window = window else {return}
                  if UserDefaults.standard.bool(forKey: "_key_AlreadyLogin") == true {
                      window.rootViewController = UIStoryboard(name: "Dashboard", bundle: nil).instantiateInitialViewController()
                  }else{
                      window.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
                  }
              }
              

              【讨论】:

                【解决方案13】:

                您如何以及从哪里展示 redVC?

                您可以将其设为 UINavigationController 的根视图控制器,因此您仍然可以推送和弹出视图控制器。

                self.navigationController?.viewControllers = [self];
                

                【讨论】:

                  【解决方案14】:

                  一旦你进入了你想设置为root的vc,只需添加你的viewDidLoad

                  let appDelegate = UIApplication.shared.delegate as! AppDelegate
                  appDelegate.window?.rootViewController = self
                  

                  *根据最佳实践,您应该检查它是否已经是根,如果不是,则执行上面的代码。

                  【讨论】:

                    【解决方案15】:

                    斯威夫特 3 AppDelegate 文件:::

                    @IBAction func btnGoBack(_ sender: UIButton){
                    
                       self.goToHomeVC()
                    }
                    
                    func goToHomeVC(){
                    
                        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                    
                        let viewController = storyboard.instantiateViewController(withIdentifier :"HomeVC") as! HomeVC
                    
                        let navController = UINavigationController.init(rootViewController: viewController)
                    
                        if let window = self.appDelegate.window, let rootViewController = window.rootViewController {
                    
                            var currentController = rootViewController
                    
                            while let presentedController = currentController.presentedViewController {
                    
                                currentController = presentedController
                            }
                    
                            currentController.present(navController, animated: true, completion: nil)
                        }
                    }
                    

                    【讨论】:

                      【解决方案16】:

                      你可以试试这个代码

                      func switchRootViewController(rootViewController: UIViewController, animated: Bool, completion: (() -> Void)?) {
                          guard let window = UIApplication.shared.keyWindow else { return }
                          if animated {
                              UIView.transition(with: window, duration: 0.5, options: .transitionCrossDissolve, animations: {
                                  let oldState: Bool = UIView.areAnimationsEnabled
                                  UIView.setAnimationsEnabled(false)
                                  window.rootViewController = rootViewController
                                  UIView.setAnimationsEnabled(oldState)
                              }, completion: { (finished: Bool) -> () in
                                  if (completion != nil) {
                                      completion!()
                                  }
                              })
                          } else {
                              window.rootViewController = rootViewController
                          }
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        任何你想设置根的视图控制器只需调用下面的函数就像

                          UIApplication.shared.setRootVC(vc)
                        
                          extension UIApplication {
                        
                            func setRootVC(_ vc : UIViewController){
                        
                                self.windows.first?.rootViewController = vc
                                self.windows.first?.makeKeyAndVisible()
                        
                              }
                          }
                        

                        【讨论】:

                          【解决方案18】:

                          只要写下这个,你就可以开始了。

                          let sb = UIStoryboard(name: "Main", bundle: nil)
                          let VC = sb.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
                          let navRootView = UINavigationController(rootViewController: VC)
                          self.present(navRootView, animated: true, completion: nil)
                          

                          【讨论】:

                          • 请解释为什么这样做。问题是什么以及为什么会解决它。
                          • UInavigationController 有一个属性允许用户设置它的根视图控制器,所以在这里我们将我们的 VC 设置为当前导航堆栈的顶部,并使其成为根视图控制器
                          【解决方案19】:

                          这就是您可以将 nib 设置为根视图控制器的方法。

                           let vc = HomeViewController(nibName: "HomeViewController", bundle: nil)
                           window = UIWindow(frame: UIScreen.main.bounds)
                           window?.rootViewController = vc
                           window?.makeKeyAndVisible()
                          

                          【讨论】:

                            【解决方案20】:

                            Link to a related question

                            此答案适用于从当前堆栈中的某处使用现有 ViewController,而无需实例化和重新配置新控制器。

                            文档说:根视图控制器提供窗口的内容视图。将视图控制器分配给该属性(以编程方式或使用 Interface Builder)将视图控制器的视图安装为窗口的内容视图。新的内容视图被配置为跟踪窗口大小,随着窗口大小的变化而变化。 如果窗口具有现有的视图层次结构,则在安装新视图之前会删除旧视图。

                            正如文档所说:如果 rootViewController 被交换,它会删除堆栈中的所有视图。 不管控制器是什么。所以从堆栈中移除 ViewController 以确保它的视图不会被移除。

                            这导致了我在以下解决方案中的情况:

                            if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
                                guard let pageVC = self.onboardingDelegate as? OnboardingPageViewController else { return } // my current stack is in a pageViewController, it also is my delegate
                                let vc = self // holding myself
                                pageVC.subViewControllers.removeLast() // removing myself from the list
                                pageVC.setViewControllers([pageVC.subViewControllers[0]], direction: .forward, animated: false, completion: nil) // remove the current presented VC
                                appDelegate.window?.rootViewController = vc
                                vc.onboardingDelegate = nil
                                appDelegate.window?.makeKeyAndVisible()
                            }
                            

                            【讨论】:

                              【解决方案21】:

                              斯威夫特 4

                               let storyBoard = UIStoryboard(name: "Your_Storyboard_Name", bundle:Bundle.main)
                               self.window = UIWindow(frame: UIScreen.main.bounds)
                               let yourVc = storyBoard.instantiateViewController(withIdentifier: "YourIdentifier") as? YourViewController
                               if let window = window {
                                   window.rootViewController = yourVc
                               }
                               window?.makeKeyAndVisible()
                              

                              【讨论】:

                                【解决方案22】:

                                Swift 4,5 及以上 如果您使用多个或单个故事板,您想设置导航控制器的不同根视图控制器,那么我使用此方法: 在我的情况下,StoryBaord 名称是 Auth。

                                    func setRootToLogin(transition :CATransition) {
                                    let storyboard = UIStoryboard(name: "Auth", bundle: nil)
                                    let loginNav =  storyboard.instantiateViewController(withIdentifier: "AuthNavigationController") as! UINavigationController
                                    window.set(rootViewController: loginNav, withTransition: transition)
                                    let vc =  window.rootViewController as! UINavigationController
                                    let loginvc = LoginViewController.instantiateAuth()
                                    vc.setViewControllers([loginvc], animated: true)
                                }
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2015-02-09
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2014-08-15
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多