viewWillDisappear:Bestimmen Sie, ob der View-Controller angezeigt wird oder ob ein Sub-View-Controller angezeigt wird

StackOverflow https://stackoverflow.com/questions/1816614

Frage

Ich habe Mühe, eine gute Lösung für dieses Problem zu finden.In einem View-Controller -viewWillDisappear: Methode muss ich einen Weg finden, um festzustellen, ob es daran liegt, dass ein Ansichtscontroller auf den Stapel des Navigationscontrollers verschoben wird, oder ob es daran liegt, dass der Ansichtscontroller verschwindet, weil er entfernt wurde.

Im Moment setze ich Flags wie isShowingChildViewController aber es wird ziemlich kompliziert.Ich glaube, ich kann es nur an der Stelle erkennen -dealloc Methode.

War es hilfreich?

Lösung

Sie können Folgendes verwenden.

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  NSArray *viewControllers = self.navigationController.viewControllers;
  if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
    // View is disappearing because a new view controller was pushed onto the stack
    NSLog(@"New view controller was pushed");
  } else if ([viewControllers indexOfObject:self] == NSNotFound) {
    // View is disappearing because it was popped from the stack
    NSLog(@"View controller was popped");
  }
}

Dies ist natürlich möglich, da der View-Controller-Stack des UINavigationControllers (der über die viewControllers-Eigenschaft verfügbar gemacht wird) zum Zeitpunkt des Aufrufs von viewWillDisappear aktualisiert wurde.

Andere Tipps

Ich denke, der einfachste Weg ist:

 - (void)viewWillDisappear:(BOOL)animated
{
    if ([self isMovingFromParentViewController])
    {
        NSLog(@"View controller was popped");
    }
    else
    {
        NSLog(@"New view controller was pushed");
    }
    [super viewWillDisappear:animated];
}

Swift:

override func viewWillDisappear(animated: Bool)
{
    if isMovingFromParentViewController
    {
        print("View controller was popped")
    }
    else
    {
        print("New view controller was pushed")
    }
    super.viewWillDisappear(animated)
}

Von Apples Dokumentation in UIViewController.h:

  

"Diese vier Methoden können in einem View-Controller-Auftritt verwendet werden   Rückrufe zu bestimmen, ob er präsentiert, entlassen oder hinzugefügt wird   oder als Kind-View-Controller entfernt. Zum Beispiel kann ein View-Controller   können überprüfen, ob sie, weil sie entlassen wurde verschwindet oder geknallt   selbst in seiner viewWillDisappear fragen: Methode durch die Überprüfung   Ausdruck ([self isBeingDismissed] || [self   isMovingFromParentViewController]). "

     

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);

     

- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

     

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);

     

- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

Also ja, die einzige dokumentierte Weg, dies zu tun, ist die folgende Art und Weise:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
    }
}

Swift 3-Version:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}

Wenn Sie wollen einfach nur wissen, ob Ihre Ansicht geknallt wird immer, ich gerade entdeckt, dass self.navigationController ist nil in viewDidDisappear, wenn es aus dem Stapel von Controllern entfernt wird. Also das ist ein einfacher Alternativer Test.

(Das habe ich entdecken, nachdem alle möglichen anderen Verrenkungen versuchen. Ich bin überrascht, es gibt keine Navigation-Controller-Protokoll einen View-Controller registrieren auf pops informiert werden. Sie nicht UINavigationControllerDelegate verwenden können, weil das tatsächlich tut reale Anzeige Arbeit.)

Swift 4

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParent
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }

In Swift:

 override func viewWillDisappear(animated: Bool) {
    if let navigationController = self.navigationController {
        if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
        }
    }

    super.viewWillDisappear(animated)

}

Ich finde Apples Dokumentation auf diese schwer zu verstehen ist. Diese Erweiterung hilft die Zustände bei jeder Navigation zu sehen.

extension UIViewController {
    public func printTransitionStates() {
        print("isBeingPresented=\(isBeingPresented)")
        print("isBeingDismissed=\(isBeingDismissed)")
        print("isMovingToParentViewController=\(isMovingToParentViewController)")
        print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
    }
}

Diese Frage ist ziemlich alt, aber ich sah es durch Zufall so dass ich am beste Praxis schreiben (afaik)

will

Sie können nur das tun,

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
 // view controller popped
}

Dies gilt für iOS7 , keine Ahnung, ob es zu irgendwelchen anderen diejenigen gilt. Von dem, was ich weiß, in viewDidDisappear bereits die Ansicht geknallt wurde. Was bedeutet, wenn Sie Abfrage self.navigationController.viewControllers Sie eine nil bekommen. Also nur überprüfen, ob das Null ist.

TL; DR

 - (void)viewDidDisappear:(BOOL)animated
 {
    [super viewDidDisappear:animated];
    if (self.navigationController.viewControllers == nil) {
        // It has been popped!
        NSLog(@"Popped and Gone");
    }
 }

Segues kann eine sehr effektive Art und Weise des Umgangs mit diesem Problem in iOS 6+ sein. Wenn Sie den besonderen Segue eine Kennung im Interface Builder angegeben haben, können Sie es in prepareForSegue überprüfen.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"LoginSegue"]) {
       NSLog(@"Push");
       // Do something specific here, or set a BOOL indicating
       // a push has occurred that will be checked later
    }
}

Ich nehme an, Sie meinen, dass Ihre Ansicht Stapel der Navigation Controller nach unten bewegt, wird durch die eine neue Ansicht drücken, wenn Sie auf den Stapel geschoben sagen. Ich würde die viewDidUnload Methode vorschlagen, mit einer NSLog Anweisung hinzufügen, etwas zu der Konsole zu schreiben, damit Sie sehen können, was los ist, können Sie eine NSLog hinzufügen möchten vielleicht viewWillDissappeer.

Hier ist eine Kategorie, die gleiche Sache wie sbrocket Antwort zu erreichen:

Rubrik:

#import <UIKit/UIKit.h>

@interface UIViewController (isBeingPopped)

- (BOOL) isBeingPopped;

@end

Quelle:

#import "UIViewController+isBeingPopped.h"

@implementation UIViewController (isBeingPopped)

- (BOOL) isBeingPopped {
    NSArray *viewControllers = self.navigationController.viewControllers;
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
        return NO;
    } else if ([viewControllers indexOfObject:self] == NSNotFound) {
        return YES;
    }
    return NO;
}

@end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top