Проверка, собирается ли UIViewController получить Popped из стека навигации?

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

Вопрос

Мне нужно знать, когда мой контроллер представления будет извлечен из стека навигации, чтобы я мог выполнить действие.

Я не могу использовать -viewWillDisappear, потому что он вызывается, когда контроллер представления перемещается за экран по ЛЮБОЙ причине (например, когда новый контроллер представления помещается сверху).

Мне особенно нужно знать, когда контроллер должен быть активирован.

Любые идеи были бы замечательными, заранее спасибо.

Это было полезно?

Решение

Я не думаю, что для этого есть явное сообщение, но вы могли бы создать подкласс UINavigationController и переопределить - popViewControllerAnimated (хотя я не пробовал это раньше сам).

В качестве альтернативы, если нет других ссылок на контроллер представления, не могли бы вы добавить к нему - dealloc?

Другие советы

Переопределите метод viewWillDisappear в представленном VC, затем проверьте флаг isMovingFromParentViewController в пределах переопределения и выполните определенную логику. В моем случае я скрываю панель инструментов навигационных контроллеров. Все еще требует, чтобы ваш представленный VC понимал, что он выдвинут, хотя и не идеален.

Попробуйте переопределить willMoveToParentViewController: (вместо viewWillDisappear: ) в вашем пользовательском подклассе UIViewController .

  

Вызывается непосредственно перед добавлением или удалением контроллера представления из контроллера представления контейнера.

- (void)willMoveToParentViewController:(UIViewController *)parent
{
    [super willMoveToParentViewController:parent];
    if (!parent) {
        // `self` is about to get popped.
    }
}

К счастью, к тому времени, когда вызывается метод viewWillDisappear, viewController уже удален из стека, поэтому мы знаем, что viewController выталкивает, потому что его больше нет в self.navigationController.viewControllers

Swift 4

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

    if let nav = self.navigationController {
        let isPopping = !nav.viewControllers.contains(self)
        if isPopping {
            // popping off nav
        } else {
            // on nav, not popping off (pushing past, being presented over, etc.)
        }
    } else {
        // not on nav at all
    }
}

Оригинальный код

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ((self.navigationController) && 
        (![self.navigationController.viewControllers containsObject:self])) {
        NSLog(@"I've been popped!");
    }
}

Это работает для меня.

- (void)viewDidDisappear:(BOOL)animated
{
    if (self.parentViewController == nil) {
        NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
        //release stuff here
    } else {
        NSLog(@"PersonViewController view just hidden");
    }
}

Вы можете поймать это здесь.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    if (viewController == YourAboutToAppearController) {
            // do something
    }
}

Это сработает непосредственно перед отображением нового вида. Никто еще не переехал. Я все время использую магию перед asinine NavigationController. Вы можете устанавливать заголовки и заголовки кнопок и делать там что угодно.

У меня та же проблема. Я попытался с viewDisDisappear, но у меня нет вызова функции :( (не знаю почему, может быть, потому что все мои VC является UITableViewController). Предложение Алекса работает нормально, но не работает, если ваш контроллер навигации отображается на вкладке «Дополнительно». В этом случае все виртуальные контроллеры ваших контроллеров навигации имеют навигационный контроллер как UIMoreNavigationController, а не контроллер навигации, который вы вложили в подклассы, поэтому навигация не будет уведомлять вас, когда виртуальный контроллер собирается отключиться.
Наконец, я решил проблему с категорией UINavigationController, просто переписать - (UIViewController *) popViewControllerAnimated: (BOOL) animated

- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
   NSLog(@"UINavigationController(Magic)");
   UIViewController *vc = self.topViewController;
   if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
      [vc performSelector:@selector(viewControllerWillBePopped)];
   }
   NSArray *vcs = self.viewControllers;
   UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
   [self popToViewController:vcc animated:YES];
   return vcc;}

У меня это хорошо работает: D

Я попробовал это:

- (void) viewWillDisappear:(BOOL)animated {
    // If we are disappearing because we were removed from navigation stack
    if (self.navigationController == nil) {
        // YOUR CODE HERE
    }

    [super viewWillDisappear:animated];
}

Идея состоит в том, что при выталкивании навигационный контроллер контроллера представления устанавливается в ноль. Поэтому, если представление должно было исчезнуть, и у него больше был навигационный контроллер, я пришел к выводу, что оно появилось. (может не работать в других сценариях).

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

Удачи, Одед.

Вы можете использовать это:

if(self.isMovingToParentViewController)
{
    NSLog(@"Pushed");
}
else
{
    NSLog(@"Popped");
}

Подкласс UINavigationController и переопределите popViewController :

Swift 3

protocol CanPreventPopProtocol {
    func shouldBePopped() -> Bool
}

class MyNavigationController: UINavigationController {
    override func popViewController(animated: Bool) -> UIViewController? {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return nil
            }
        }
        return super.popViewController(animated: animated)
    }

    //important to prevent UI thread from freezing
    //
    //if popViewController is called by gesture recognizer and prevented by returning nil
    //UI will freeze after calling super.popViewController
    //so that, in order to solve the problem we should not return nil from popViewController
    //we interrupt the call made by gesture recognizer to popViewController through
    //returning false on gestureRecognizerShouldBegin
    //
    //tested on iOS 9.3.2 not others
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return false
            }
        }

        return true
    }

}

Возможно, вы могли бы использовать метод протокола UINavigationBarDelegate navigationBar: shouldPopItem.

Попробуйте сделать эту проверку в viewwilldisappear if ([self.navigationController.viewControllers indexOfObject: self] == NSNotFound) { // всплывающее окно этого представления произошло. }

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top