如何正确地closures作为模式呈现的UINavigationController?
在我的TabBarViewController
,我创build了一个UINavigationController并将其作为模式呈现。
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)
在我的MessageViewController
里面,这是我想要解雇它的:
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") }
问题是,当我到达根视图控制器,并试图消除孩子和UINavigationController,我的MessagesViewController
deinit不会被调用。 有些东西是坚持的 – 最有可能的是UINavigationController
您的控制器层次结构如下所示:
UITabViewController | | presents | UINavigationController | | contains view controllers | [root, MessagesViewController]
现在,如果你在MessagesViewController
里面,那么它的navigationController
是正在呈现的那个,这是你应该解雇的那个,但是在MessagesViewController
上调用dismiss
也应该工作。
但是,问题是closures导航控制器不会删除其视图控制器。 看来你是持有你的导航控制器(因为你正在使用self.navController
呈现它),所以状态将成为
UITabViewController | | self.navController holds a reference to | UINavigationController | | contains view controllers | [root, MessagesViewController]
要正确销毁MessagesViewController
您将不得不放开navController
否则将不得不popup根目录(从视图层次结构中删除MessagesViewController
)。
典型的解决scheme是根本不保存对navController
的引用。 展示时,您总是可以创build一个新的UINavigationController
。 另一个解决scheme是使用一个委托 – 而不是从MessagesViewController
内部解雇,让它callback给主持人,这将打电话给
self.navController.dismissViewControllerAnimated(true, completion: { self.navController = nil; });
尝试这个
func swipedRightAndUserWantsToDismiss(){ self.navigationController.dismissViewControllerAnimated(false, completion:nil); }
不需要navController成员。 使用下面的代码来呈现你的MessagesViewController。
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController let pesentingNavigationController = UINavigationController(rootViewController: messageVC) self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
你的解雇视图控制器代码将是
func swipedRightAndUserWantsToDismiss() { self.navigationController.dismissViewControllerAnimated(true, completion: nil) }
我build议你为你的UINavigationController
使用其他的初始化工具:
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController let navController = UINavigationController(rootViewController: messageVC) self.presentViewController(self.navController, animated: true, completion: nil)
要变傻,干脆就这样做
func swipedRightAndUserWantsToDismiss() { self.navigationController.dismissViewControllerAnimated(true, completion: nil) }
如果你只想呈现一个视图控制器,那么你可以直接展示该视图控制器,而不需要为该视图控制器设置一个导航控制器。
但是当我们需要从该视图控制器导航时,我们需要将视图控制器作为导航控制器的根视图。 所以我们可以从那个呈现的视图控制器中导航。
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController let MynavController = UINavigationController(rootViewController: messageVC) self.presentViewController(MynavController, animated: true, completion: nil)
并从该视图控制器,你可以推到另一个视图控制器,也可以从另一个视图控制器popup。
从呈现的视图控制器,在这里messageVC
,我们不得不驳回作为
func swipedRightAndUserWantsToDismiss() { self.dismissViewControllerAnimated(true, completion: nil) }
这将成功消除messageVC
并从我们提供messageVC
地方回到原始视图messageVC
。
这是使用导航控制器执行presentViewController
的正确stream程,以继续视图控制器之间的导航。
如果不确定是否显示或推送messageVC,则可以通过此答案查看。
而迅捷的版本来检查是
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 }
所以我们最后的解雇行为就像
func swipedRightAndUserWantsToDismiss() { if self.isModal() == true { self.dismissViewControllerAnimated(true, completion: nil) } else { self.navigationController?.popViewControllerAnimated(true) } }
这就是我在Objective C中解决问题的方法
你可以在你的self.navigationController本身上调用dismissViewControllerAnimated:NO 。
目标C
[self.navigationController dismissViewControllerAnimated:NO completion:nil];
迅速
self.navigationController.dismissViewControllerAnimated(false, completion: nil)
在Swift 3中,这是通过以下方式实现的:
self.navigationController?.dismiss(animated: true, completion: nil)