viewWillDisappear: Определите, выталкивается ли контроллер представления или показывает контроллер подвида - PullRequest
132 голосов
/ 29 ноября 2009

Я изо всех сил пытаюсь найти хорошее решение этой проблемы. В методе -viewWillDisappear: контроллера представления мне нужно найти способ определить, происходит ли это из-за того, что контроллер представления помещается в стек контроллера навигации, или из-за того, что контроллер представления исчезает из-за его выталкивания.

В данный момент я устанавливаю такие флаги, как isShowingChildViewController, но это становится довольно сложно. Единственный способ, которым я могу обнаружить это, - метод -dealloc.

Ответы [ 12 ]

228 голосов
/ 29 ноября 2009

Вы можете использовать следующее.

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

Это, конечно, возможно, потому что стек контроллера представления UINavigationController (предоставляемый через свойство viewControllers) был обновлен ко времени вызова viewWillDisappear.

128 голосов
/ 25 июня 2013

Я думаю, что самый простой способ:

 - (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)
}
57 голосов
/ 02 ноября 2015

Из документации Apple в UIViewController.h:

"Эти четыре метода могут использоваться в представлении контроллера представления обратные вызовы, чтобы определить, представлен ли он, отклонен или добавлен или удален как дочерний контроллер представления. Например, контроллер представления может проверить, исчезает ли он, потому что он был уволен или выскочил спрашивая себя в его viewWillDisappear: метод, проверяя выражение ([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);

Так что да, единственный документированный способ сделать это - это следующий способ:

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

Swift 3 версия:

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

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}
18 голосов
/ 28 января 2010

Если вы просто хотите узнать, работает ли ваше представление, я только что обнаружил, что self.navigationController равно nil в viewDidDisappear, когда оно удаляется из стека контроллеров. Это простой альтернативный тест.

(Это я обнаружил после того, как попробовал все виды других искажений. Я удивлен, что нет протокола контроллера навигации, чтобы зарегистрировать контроллер представления, чтобы получать уведомления о всплывающих окнах. Вы не можете использовать UINavigationControllerDelegate, потому что на самом деле это действительно работает на дисплее .)

11 голосов
/ 10 января 2017

Свифт 4

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParent
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }
6 голосов
/ 22 октября 2014

В Свифт:

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

    super.viewWillDisappear(animated)

}
2 голосов
/ 11 апреля 2017

Мне кажется, что документацию Apple по этому вопросу трудно понять. Это расширение помогает видеть состояния при каждой навигации.

extension UIViewController {
    public func printTransitionStates() {
        print("isBeingPresented=\(isBeingPresented)")
        print("isBeingDismissed=\(isBeingDismissed)")
        print("isMovingToParentViewController=\(isMovingToParentViewController)")
        print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
    }
}
1 голос
/ 04 апреля 2014

Segues может быть очень эффективным способом решения этой проблемы в iOS 6+. Если вы указали идентификатор конкретной программы в Интерфейсном Разработчике, вы можете проверить его в prepareForSegue.

- (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
    }
}
1 голос
/ 03 апреля 2014

Это относится к iOS7 , не знаю, применимо ли оно к любым другим. Из того, что я знаю, в viewDidDisappear представление уже всплыло. Это означает, что при запросе self.navigationController.viewControllers вы получите nil. Так что просто проверьте, если это ноль.

TL; DR

 - (void)viewDidDisappear:(BOOL)animated
 {
    [super viewDidDisappear:animated];
    if (self.navigationController.viewControllers == nil) {
        // It has been popped!
        NSLog(@"Popped and Gone");
    }
 }
1 голос
/ 04 сентября 2013

Этот вопрос довольно старый, но я увидел его случайно, поэтому хочу опубликовать лучшие практики (afaik)

Вы можете просто сделать

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
 // view controller popped
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...