Ios 如何正确关闭';它以模态形式呈现?

Ios 如何正确关闭';它以模态形式呈现?,ios,objective-c,swift,Ios,Objective C,Swift,在我的选项卡BarViewController中,我创建了一个UINavigationController,并将其显示为模式 var navController = UINavigationController() let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController self.presentVie

在我的
选项卡BarViewController
中,我创建了一个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

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

我建议您对
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)
}

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

UITabViewController
    |
    | presents
    |
UINavigationController
    |
    | contains view controllers
    |
[root, MessagesViewController]
现在,如果您在
MessagesViewController
中,那么它的
navigationController
就是当前显示的控制器,您应该解除该控制器,但在
MessagesViewController
上调用
dislose
也应该起作用

但是,问题是,取消导航控制器不会删除其视图控制器。似乎您正在使用导航控制器(因为您使用的是
self.navController
)来显示它),因此状态将变为

UITabViewController
    |
    | self.navController holds a reference to
    |
UINavigationController
    |
    | contains view controllers
    |
[root, MessagesViewController]
要正确销毁
MessagesViewController
,您必须放开
navController
,或者必须跳转到root(从而从视图层次结构中删除
MessagesViewController

典型的解决方案是根本不保存对
navController
的引用。在演示时,您始终可以创建一个新的
UINavigationController
。 另一种解决方案是使用委托,而不是从
MessagesViewController
内部解除委托,而是让它回拨演示者,演示者将调用

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

navController不需要有成员。使用以下代码显示您的MessagesViewController

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)
您的视图控制器代码将为

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

如果只想显示viewcontroller,则可以直接显示该viewcontroller,而无需为特定的viewcontroller使用导航控制器

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)
但是当我们需要从显示的视图控制器导航时,我们需要将视图控制器作为导航控制器的根视图。这样我们就可以从显示的视图控制器进行导航

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)
从显示的视图控制器,您可以推送到另一个视图控制器,也可以从另一个视图控制器弹出

let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let pesentingNavigationController = UINavigationController(rootViewController: messageVC)
self.presentViewController(pesentingNavigationController, animated: true, completion: nil)
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
let MynavController = UINavigationController(rootViewController: messageVC)
self.presentViewController(MynavController, animated: true, completion: nil)
从展示的视图控制器来看,这里是
messageVC
,我们必须将其视为

func swipedRightAndUserWantsToDismiss() {
  self.dismiss(animated: true, completion: nil)
}
它将成功地关闭
messageVC
,并返回到我们展示
messageVC
的源视图控制器

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

如果您不确定是否显示或推送了messageVC,则可以检查它

而swift版本可以检查这一点

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.dismiss(animated: true, completion: nil)
            }
            else {
                self.navigationController?.popViewControllerAnimated(true)
            }

        }

这就是我在目标C中解决问题的方法

您可以在self.navigationController本身上调用dismissViewControllerAnimated:NO

目标C

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

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

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

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

您可以使用以下命令正确地解除Swift 4中显示为模式的
UINavigationController

self.navigationController?.popViewController(animated: true)

谢谢如果堆栈中有许多视图控制器,但我的委托调用了
dismissViewControllerAnimated
,然后将其设置为nil,它会拒绝堆栈中的所有视图控制器吗?当您放弃对
navController
的所有引用时,如果您不在其他地方保留其所有视图控制器,则其所有视图控制器都将被销毁。您也无法解除已设置为rootviewcontroller的视图控制器。因此,如果: