Dans ma TabBarViewController
, je crée un UINavigationController et le présente en tant que modal.
var navController = UINavigationController()
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
self.presentViewController(self.navController, animated: false, completion: nil)
self.navController.pushViewController(messageVC, animated: false)
Dans ma MessageViewController
, voici comment je veux le rejeter:
func swipedRightAndUserWantsToDismiss(){
if self == self.navigationController?.viewControllers[0] {
self.dismissViewControllerAnimated(true, completion: nil) //doesn't deinit
}else{
self.navigationController?.popViewControllerAnimated(true) //deinits correctly
}
}
deinit{
print("Deinit MessagesViewController")
}
Le problème est que, lorsque j'arrive à la vue View Controller racine et que j'essaie de rejeter l'enfant et le contrôleur UINavigationController, ma MessagesViewController
deinit n'est pas appelée. Quelque chose s'y tient - très probablement UINavigationController
Votre hiérarchie de contrôleur ressemble à ceci:
UITabViewController
|
| presents
|
UINavigationController
|
| contains view controllers
|
[root, MessagesViewController]
Maintenant, si vous êtes dans MessagesViewController
, alors sa navigationController
est celle qui est présentée et c'est celle que vous devriez ignorer, mais appeler dismiss
sur MessagesViewController
devrait également fonctionner.
Cependant, le problème est que le fait de fermer le contrôleur de navigation ne supprimera pas ses contrôleurs de vue. Il semble que vous vous en teniez à votre contrôleur de navigation (puisque vous le présentez à l’aide de self.navController
).
UITabViewController
|
| self.navController holds a reference to
|
UINavigationController
|
| contains view controllers
|
[root, MessagesViewController]
Pour détruire correctement MessagesViewController
, vous devrez soit lâcher la navController
ou vous devrez passer à la racine (ce qui supprimera MessagesViewController
de la hiérarchie des vues).
La solution typique serait de ne pas enregistrer la référence à navController
. Vous pouvez toujours créer une nouvelle UINavigationController
lors de la présentation de . Une autre solution consiste à utiliser un délégué - au lieu de rejeter de l'intérieur MessagesViewController
, laissez-le rappeler à l'animateur,
self.navController.dismiss(animated: true) {
self.navController = nil
}
Essaye ça
func swipedRightAndUserWantsToDismiss(){
self.navigationController.dismissViewControllerAnimated(false, completion:nil);
}
si vous souhaitez simplement présenter un contrôleur de vue, vous pouvez alors présenter ce contrôleur de vue directement et vous n'avez pas besoin de prendre un contrôleur de navigation pour ce contrôleur de vue particulier.
Mais lorsque nous devons naviguer à partir du contrôleur de vue présenté, nous devons utiliser un contrôleur de vue en tant que vue racine du contrôleur de navigation. Pour que nous puissions naviguer à partir du contrôleur de vue présenté.
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)
et à partir de ce contrôleur de vue présenté, vous pouvez pousser vers un autre contrôleur de vue et également accéder à un autre contrôleur de vue.
Et à partir du contrôleur de vue présenté, ici messageVC
, nous devons rejeter cela comme
func swipedRightAndUserWantsToDismiss() {
self.dismiss(animated: true, completion: nil)
}
qui rejettera messageVC
avec succès et reviendra au contrôleur de vue Origin à partir duquel nous avons présenté messageVC
.
C’est le bon flux pour exécuter presentViewController
avec le contrôleur de navigation, afin de poursuivre la navigation entre les contrôleurs de vue.
Et pour plus si vous n'êtes pas sûr que le messageVC est présenté ou poussé, vous pouvez le vérifier par cette réponse .
Et la version Swift pour vérifier cela est
func isModal() -> Bool {
if((self.presentingViewController) != nil) {
return true
}
if(self.presentingViewController?.presentedViewController == self) {
return true
}
if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
return true
}
if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
return true
}
return false
}
Donc, notre action finale pour rejeter est comme
func swipedRightAndUserWantsToDismiss() {
if self.isModal() == true {
self.dismiss(animated: true, completion: nil)
}
else {
self.navigationController?.popViewControllerAnimated(true)
}
}
Pas besoin d'avoir un membre pour navController. Utilisez le code suivant pour présenter votre MessagesViewController.
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
Votre code de contrôleur de vue de renvoi sera
func swipedRightAndUserWantsToDismiss() {
self.navigationController.dismiss(animated: true, completion: nil)
}
Dans Swift 3, ceci est réalisé avec:
self.navigationController?.dismiss(animated: true, completion: nil)
Je vous suggère d'utiliser l'autre initialiseur pour votre UINavigationController
:
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let navController = UINavigationController(rootViewController: messageVC)
self.presentViewController(self.navController, animated: true, completion: nil)
Pour dimiss, il suffit de faire
func swipedRightAndUserWantsToDismiss() {
self.navigationController.dismissViewControllerAnimated(true, completion: nil)
}
Voici comment je résous le problème dans l’objectif C.
Vous pouvez appeler licencierViewControllerAnimated: NO sur votre self.navigationController lui-même.
Objectif c
[self.navigationController dismissViewControllerAnimated:NO completion:nil];
Rapide
self.navigationController.dismissViewControllerAnimated(false, completion: nil)
Vous pouvez utiliser ce qui suit pour supprimer correctement une UINavigationController
présentée comme modal dans Swift 4:
self.navigationController?.popViewController(animated: true)