webentwicklung-frage-antwort-db.com.de

Wie kann ich einen UINavigationController, der als modal dargestellt wird, korrekt verwerfen?

In meiner TabBarViewController erstelle ich einen UINavigationController und präsentiere ihn als 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)

In meiner MessageViewController möchte ich es so abweisen:

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")
}

Das Problem ist, dass mein MessagesViewController deinit nicht aufgerufen wird, wenn ich zum Root-View-Controller komme und versuche, das untergeordnete Element und den UINavigationController zu entlassen. Etwas hält daran fest - höchstwahrscheinlich UINavigationController

19
TIMEX

Ihre Controller-Hierarchie sieht folgendermaßen aus:

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

Wenn Sie sich in MessagesViewController befinden, dann ist dessen navigationController diejenige, die präsentiert wird, und dies ist diejenige, die Sie abweisen sollten, aber der Aufruf von dismiss für MessagesViewController sollte ebenfalls funktionieren.

Das Problem ist jedoch, dass das Entfernen des Navigationscontrollers seine Ansichtscontroller nicht entfernt. Es scheint, als würden Sie sich an Ihren Navigationscontroller halten (da Sie ihn mit self.navController präsentieren), so dass der Status angezeigt wird

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

Um MessagesViewController richtig zu vernichten, müssen Sie entweder die navController loslassen oder zum root gehen (wodurch MessagesViewController aus der Ansichtshierarchie entfernt wird).

Die typische Lösung wäre, einen Verweis auf navController nicht zu speichern. Sie können immer eine neue UINavigationController erstellen, wenn Sie präsentieren . Eine andere Lösung ist die Verwendung eines Delegaten. Statt MessagesViewController abzulehnen, rufen Sie den Moderator an, der angerufen wird

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

Versuche dies 

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

wenn Sie nur einen Viewcontroller präsentieren möchten, können Sie diesen Viewcontroller direkt präsentieren, ohne dass Sie einen Navigationscontroller für diesen Viewcontroller benötigen.

Wenn wir jedoch von diesem präsentierten View-Controller aus navigieren müssen, müssen wir einen View-Controller als Stammansicht des Navigationscontrollers verwenden. Damit wir von diesem präsentierten View-Controller aus navigieren können.

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

und von diesem dargestellten Ansichtscontroller aus können Sie auf einen anderen Ansichtscontroller drücken und auch von einem anderen Ansichtscontroller aus springen.

Und vom vorgestellten View Controller, hier messageVC, müssen wir das als verwerfen

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

dies wird messageVC erfolgreich verwerfen und zu Origin viewcontroller zurückkehren, von wo aus wir messageVC vorgestellt haben.

Dies ist der richtige Ablauf, um presentViewController mit dem Navigationscontroller auszuführen, um die Navigation zwischen den Viewcontrollern fortzusetzen.

Und wenn Sie sich nicht sicher sind, ob messageVC angezeigt oder gepusht wird, können Sie dies überprüfen anhand dieser Antwort .

Und die Swift-Version soll das überprüfen 

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
}

Unsere abschließende Klage ist also wie folgt 

func swipedRightAndUserWantsToDismiss() {

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

        }
5
Max

Kein Mitglied für navController. Verwenden Sie den folgenden Code, um Ihren MessagesViewController zu präsentieren.

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

Sie werden den Code für den Ansichts-Controller verwerfen 

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

In Swift 3 wird dies erreicht mit:

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

Ich schlage vor, dass Sie den anderen Initializer für Ihre UINavigationController verwenden:

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

Zum Ablegen einfach tun 

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

So löse ich das Problem in Ziel C. 

Sie können dismissViewControllerAnimated aufrufen: NO auf Ihrem self.navigationController sich selbst.

Ziel c

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

Swift

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

Sie können Folgendes verwenden, um eine UINavigationController, die in Swift 4 als Modal dargestellt wird, richtig zu verwerfen:

self.navigationController?.popViewController(animated: true)
0
Faris