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.
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
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
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)
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)
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
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)
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?
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
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];
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()
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.
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
})
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()
}
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
}
}
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.
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)
}
}