簡體   English   中英

如何正確解雇一個呈現為模態的UINavigationController?

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

在我的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)

在我的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也應該有效。

但是,問題是解雇導航控制器不會刪除其視圖控制器。 看起來你正在堅持你的導航控制器(因為你使用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
}

嘗試這個

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

如果你只想呈現一個viewcontroller,那么你可以直接呈現那個viewcontroller而不需要為那個特定的viewcontroller帶一個導航控制器。

但是當我們需要從顯示的視圖控制器導航時,我們需要將視圖控制器作為導航控制器的根視圖。 這樣我們就可以從那個呈現的視圖控制器中導航。

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地方返回到origin viewcontroller。

這是使用導航控制器執行presentViewController的正確流程,以繼續視圖控制器之間的導航。

如果您不確定是否呈現或推送了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.dismiss(animated: true, completion: nil)
            }
            else {
                self.navigationController?.popViewControllerAnimated(true)
            }

        }

無需擁有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.dismiss(animated: true, completion: nil)
}

我建議你為你的UINavigationController使用另一個初始化器:

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

為了dimiss,干脆做

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

這就是我在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)

您可以使用以下命令正確關閉在Swift 4中作為模式呈現的UINavigationController

self.navigationController?.popViewController(animated: true)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM