web-dev-qa-db-fra.com

Swift ios définit un nouveau contrôleur de vue racine

Je me demande s'il est possible de définir une nouvelle racine VC?

Mon application obtient init avec un contrôleur uinavigation qui a une vue sous forme de tableau pour le VC racine.

Ensuite, à partir de la vue Table, je lance une autre transition vers une fenêtre de connexion (présente modalement). Si vous vous connectez ensuite, vous vous retrouvez dans la page red VC/account. Ce que je veux faire maintenant, c'est définir le VC rouge comme étant la nouvelle racine VC de l'application et supprimer tous les VC sous-jacents. Pour pouvoir afficher un bouton/une icône de menu au lieu d'un bouton "Précédent"

J'ai trouvé ceci mais je ne comprends pas comment l'utiliser:

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)

Mais je ne peux pas le faire fonctionner. Il est donc possible de faire en sorte que le vc rouge de la photo devienne le nouveau VC racine.

 enter image description here

15
user2722667

Peut-être devriez-vous essayer ceci

 let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
 let redViewController = mainStoryBoard.instantiateViewControllerWithIdentifier("respectiveIdentifier") as! ViewController
 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 appDelegate.window?.rootViewController = redViewController
26
Vashum

Mise à jour 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
20
footyapps27

UINavigationController a une propriété viewControllers, qui est un NSArray. Vous pouvez la remplacer par votre propre NSArray de contrôleurs de vue.

Cela peut être fait comme le montre l'exemple de code ci-dessous.

let newViewController = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewControllerollerID") as! YourViewController

    let customViewControllersArray : NSArray = [newViewController]
    self.navigationController?.viewControllers = customViewControllersArray as! [UIViewController]

Et si vous souhaitez afficher ce nouveau contrôleur de vue racine, vous pouvez simplement appeler la méthode popToRootViewController () de UINavigationController.

self.navigationController?.popToRootViewControllerAnimated(true)
6
Tushar Korde

Pour que l'extrait de code de la question initiale fonctionne, il a fallu modifier la troisième ligne.

let navigationController = self.navigationController!

J'utilise ce code dans un @IBAction dans le contrôleur de vue qui précède le nouveau contrôleur de vue racine.

En utilisant le code d'origine, je recevais une erreur indiquant que mon contrôleur de vue n'avait aucun membre appelé window. Après avoir examiné la documentation , je n’ai trouvé aucune propriété nommée window. Je me demande si le bloc de code original ci-dessus était destiné à être utilisé dans un fichier UINavigationController.

Voici le bloc dans son intégralité.

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)
5
Amelia

Swift 4 réponse 

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
4
Akila Wasala

Vous pouvez utiliser ce morceau de code:

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)
2
Deepti Raghav

Je me demande s'il est possible de définir une nouvelle racine VC?

Oui, c'est possible. Comment vous le faites dépend du contexte ...

Mon application obtient init avec un contrôleur uinavigation qui a une vue sous forme de tableau pour le VC racine.

Il y a en fait deux choses qu'on appelle communément le "contrôleur de vue racine": 

  • UIWindow a une propriété rootViewController qui est accessible en écriture.

  • UINavigationController n'a pas de propriété rootViewController, mais il a un initialiseur appelé -initWithRootViewController:. Vous pouvez définir le contrôleur de vue "racine" du contrôleur de navigation en définissant sa propriété viewControllers.

On dirait que vous essayez de changer le contrôleur de vue racine de la fenêtre, mais le code que vous affichez ne fait que modifier la propriété viewControllers du contrôleur de navigation. Essayez de définir directement la propriété rootViewController de la fenêtre. Comprenez cependant que si vous adoptez cette approche, le contrôleur de navigation disparaîtra également. Si vous voulez conserver le contrôleur de navigation, par contre, choisissez l’approche actuelle.

Mais je ne peux pas le faire fonctionner. Il est donc possible de faire en sorte que le vc rouge de la photo devienne le nouveau VC racine.

Plus d'informations ici seraient utiles. Que voulez-vous dire par "n'arrive pas à le faire fonctionner"? Que se passe-t-il et qu'espérez-vous qu'il se passe?

2
Caleb

Vous pouvez utiliser ce code lorsque vous cliquez sur le bouton de connexion: -

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

Comment et d'où présentez-vous le redVC?

Vous pouvez en faire un contrôleur de vue racine de votre UINavigationController, de sorte que vous ayez toujours la possibilité de pousser et de décompresser les contrôleurs de vue.

self.navigationController?.viewControllers = [self];
1
ArturOlszak

Swift 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
   }
 self.window?.makeKeyAndVisible()
0
Sandeep Kakde

Pour Swift 4.0 .

Dans votre méthode AppDelegate.Swift fichier dans didfinishedlaunchingWithOptions , insérez le code suivant.

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
}

J'espère que cela fonctionnera très bien.

0
mumu

Si vous devez définir rootViewController avec certaines animations, voici le code:

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
})
0
Amrit Sidhu

Lien vers une question connexe

Cette réponse s'applique à l'utilisation d'un ViewController existant à partir de quelque part dans la pile actuelle sans instancier ni reconfigurer un nouveau contrôleur.

La documentation indique: Le contrôleur de vue racine fournit la vue du contenu de la fenêtre. L'affectation d'un contrôleur de vue à cette propriété (par programme ou à l'aide d'Interface Builder) installe la vue du contrôleur de vue en tant que vue de contenu de la fenêtre. La nouvelle vue de contenu est configurée pour suivre la taille de la fenêtre, en fonction de ses modifications. Si la fenêtre a une hiérarchie de vues existante, les anciennes vues sont supprimées avant les nouvelles.

Exactement comme le dit la documentation: Il supprime toutes les vues de la pile si le rootViewController est échangé. Peu importe ce qu'il y a avec le contrôleur. Supprimez donc le ViewController de la pile pour vous assurer que sa vue ne sera pas supprimée. 

Cela a abouti dans mon cas à la solution suivante:

    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()
    }
0
Viktor_DE

Vous pouvez essayer ce code

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
    }
}
0
Anirudha Mahale

une fois que vous êtes dans le vc que vous voulez définir en tant que root, ajoutez simplement dans votre viewDidLoad :

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

* Selon meilleure pratique, vous devriez vérifier si c'est déjà la racine, sinon exécuter le code ci-dessus.

0
MLBDG

Swift 3 Fichier 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)
    }
}
0
Deepak Tagadiya