ios 如何正确关闭显示为模式的 UINavigationController?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35416525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:30:49  来源:igfitidea点击:

How to correctly dismiss a UINavigationController that's presented as a modal?

iosobjective-cswift

提问by TIMEX

In my TabBarViewController, I create a UINavigationController and present it as a modal.

在 my 中TabBarViewController,我创建了一个 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)

Inside my MessageViewController, this is how I want to dismiss it:

在 my 中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")
}

The problem is that when I get to the root View Controller and try to dismiss both the child and the UINavigationController, my MessagesViewControllerdeinit does not get called. Something's holding on to it -- most likely UINavigationController

问题是,当我到达根视图控制器并尝试关闭子视图控制器和 UINavigationController 时,我的MessagesViewControllerdeinit 没有被调用。有什么东西在坚持着它——很可能是 UINavigationController

采纳答案by Sulthan

Your controller hierarchy looks like this:

您的控制器层次结构如下所示:

UITabViewController
    |
    | presents
    |
UINavigationController
    |
    | contains view controllers
    |
[root, MessagesViewController]

Now, if you are inside MessagesViewController, then its navigationControlleris the one that is being presented and that's the one you should be dismissing but calling dismisson MessagesViewControllershould work too.

现在,如果你在里面MessagesViewController,那么它navigationController就是被呈现的那个,那是你应该解雇的那个,但也应该调用dismissMessagesViewController

However, the problem is that dismissing the navigation controller won't remove its view controllers. It seems you are holding to your navigation controller (since you are presenting it using self.navController) so the state will become

然而,问题是关闭导航控制器不会删除它的视图控制器。似乎您正在握住导航控制器(因为您使用的是呈现它self.navController),因此状态将变为

UITabViewController
    |
    | self.navController holds a reference to
    |
UINavigationController
    |
    | contains view controllers
    |
[root, MessagesViewController]

To properly destroy MessagesViewControlleryou will have to either let go of the navControlleror you will have to pop to root (thus removing MessagesViewControllerfrom view hierarchy).

要正确销毁,MessagesViewController您必须要么放手,要么navController必须弹出到根目录(从而MessagesViewController从视图层次结构中删除)。

The typical solution would be not to save a reference to navControllerat all. You could always create a new UINavigationControllerwhen presenting. Another solution is using a delegate - instead of dismissing from inside MessagesViewController, let it call back to the presenter, which would call

典型的解决方案是根本不保存对的引用navController。你总是可以UINavigationController在演示时创建一个新的。另一种解决方案是使用委托 - 而不是从内部解雇,而是MessagesViewController让它回调给演示者,后者会调用

self.navController.dismiss(animated: true) {
     self.navController = nil
}

回答by Shehzad Ali

Try this

尝试这个

func swipedRightAndUserWantsToDismiss(){
    self.navigationController.dismissViewControllerAnimated(false, completion:nil);
}

回答by Max

if you want to just present a viewcontroller, then directly you can present that viewcontroller and no need to take a navigation controller for that particular viewcontroller.

如果您只想呈现一个视图控制器,那么您可以直接呈现该视图控制器,而无需为该特定视图控制器采用导航控制器。

But when we need to navigate from that presented view controller then we need to take a view controller as a root view of navigation controller. So that we can navigate from that presented view controller.

但是当我们需要从呈现的视图控制器进行导航时,我们需要将视图控制器作为导航控制器的根视图。这样我们就可以从呈现的视图控制器进行导航。

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)

and from that presented view controller, you can push to another view controller and also pop from another view controller.

从那个呈现的视图控制器,你可以推送到另一个视图控制器,也可以从另一个视图控制器弹出。

And from presented view controller, here messageVC, we have to dismiss that as

从呈现的视图控制器,这里messageVC,我们必须将其视为

func swipedRightAndUserWantsToDismiss() {
  self.dismiss(animated: true, completion: nil)
}

which will dismiss messageVCsuccessfully and come back to origin viewcontroller from where we have presented messageVC.

这将messageVC成功关闭并从我们呈现的地方返回到原点视图控制器messageVC

This is the right flow to perform presentViewControllerwith navigation controller, to continue the navigation between the view controllers.

这是presentViewController使用导航控制器执行的正确流程,以继续视图控制器之间的导航。

And for more if you are not sure that messageVC is presented or pushed, then you can check it by this answer.

如果您不确定是否显示或推送了 messageVC,则可以通过此答案查看更多信息。

And the swift version to check that is

快速版本来检查是

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
}

So our final action to dismiss is like

所以我们解雇的最后行动就像

func swipedRightAndUserWantsToDismiss() {

            if self.isModal() == true {
                self.dismiss(animated: true, completion: nil)
            }
            else {
                self.navigationController?.popViewControllerAnimated(true)
            }

        }

回答by Arun Ammannaya

No need to have member for navController. Use following code to present your MessagesViewController.

无需为 navController 设置成员。使用以下代码来呈现您的 MessagesViewController。

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)

Your dismiss view controller code will be

您的关闭视图控制器代码将是

func swipedRightAndUserWantsToDismiss() {
  self.navigationController.dismiss(animated: true, completion: nil)
}

回答by Faris

You can use the following to correctly dismiss a UINavigationControllerthat's presented as a modal in Swift 4:

您可以使用以下内容正确关闭UINavigationController在 Swift 4 中显示为模态的 a:

self.navigationController?.popViewController(animated: true)

回答by TechBee

This is how I solve the problem in Objective C.

这就是我在 Objective C 中解决问题的方法。

You can call dismissViewControllerAnimated:NOon your self.navigationControlleritself.

你可以在你的self.navigationController上调用dismissViewControllerAnimated:NO

Objective C

目标 C

[self.navigationController dismissViewControllerAnimated:NO completion:nil];

Swift

迅速

self.navigationController.dismissViewControllerAnimated(false, completion: nil)

回答by dannrob

In Swift 3 this is achieved with:

在 Swift 3 中,这是通过以下方式实现的:

self.navigationController?.dismiss(animated: true, completion: nil)

回答by Kelvin Lau

I suggest you use the other initializer for your UINavigationController:

我建议您使用其他初始化程序UINavigationController

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let navController = UINavigationController(rootViewController: messageVC)
self.presentViewController(self.navController, animated: true, completion: nil)

To dimiss, simply do

要关闭,只需执行

func swipedRightAndUserWantsToDismiss() {
  self.navigationController.dismissViewControllerAnimated(true, completion: nil)
}