viewWillAppear не вызывается после popToViewController

У меня небольшая проблема. Я работаю над простым приложением с контроллерами представлений в контроллере навигации, например: A->B->C (-> являются модальными переходами). Представление A является корневым контроллером, и мне нужно вернуться к A из C. Если Я вызываю метод popToViewController из B, A запускаю viewWillAppear; если я вызываю popToViewController из C (в A), viewWillAppear для A не вызывается. Как я могу решить это? (Работает на Xcode7 и iOS 9)

ViewController A

#import "ViewControllerA.h"
#import "ViewControllerB.h"

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self setupSceneA];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"goToB"]) {
       ViewControllerB *b = [segue destinationViewController];
    }
}

ViewController B

#import "ViewControllerB.h"
#import "ViewControllerC.h"

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self setupSceneB];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"goToC"]) {
       ViewControllerC *c = [segue destinationViewController];
    }
}

- (IBAction)backToAButton:(id)sender {
    [self dismissViewControllerAnimated:NO completion:nil];
}

ViewController C

#import "ViewControllerC.h";

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self setupSceneC];
}


- (IBAction)backToBButton:(id)sender {
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (IBAction)backToAButton:(id)sender {
    [[self parentViewController] dismissViewControllerAnimated:NO completion:nil];
}

2 ответа

Решение

Это должен быть ваш дизайн:

Контроллер A -> модальный переход к контроллеру Nav (контроллер B является корневым контроллером) -> передача перехода к контроллеру C.

Так что если вы хотите перейти с C на B, вы делаете поп.

Когда вы хотите перейти из B в A или из C в A, вы делаете отставку.

Если вы реализуете один из этих двух случаев, представленных ниже, вы обязательно получите viewWillAppear и убедитесь, что вы написали это правильно с этим super

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // Your code goes here
}

Случай 1 - Использование контроллера навигации

Если вы хотите перемещаться с одного ViewController на другой, вам нужно, чтобы все они были в одном стеке навигации. Это означает, что каждый раз, когда вы хотите открыть новый View Controller, вам нужно сделать что-то вроде этого:

 [self.navigationController pushViewController:nextVC animated:YES];

вместо этого

[self presentViewController:nextVC animated:YES completion:nil];

И после этого, если у вас уже есть все VC в этом же навигационном контроллере, вы можете использовать этот код, чтобы вернуться на один шаг назад (например, от B к A, от C к B)

[self.navigationController popViewControllerAnimated:YES];

И вы можете использовать этот код, чтобы перейти к началу (например, от C до A)

[self.navigationController popToRootViewControllerAnimated:YES];


Случай 2 - Обычный цикл (похоже на то, что вам нужно)
Это простой случай, но вы должны быть осторожнее с вашим кодом. Вы можете просто получить родительский родитель, чтобы оставить текущий View Controller

[[[selfingingViewController] presentingViewController] dismissViewControllerAnimated:NO завершение:nil];



Примечание: Вы не можете использовать функции контроллера навигации с функциями модального представления. Толчок с поп, настоящее с увольнением


ОБНОВЛЕНИЕ 1

Модальные сегменты создают вложенное соединение (одна строка дерева). Если вы закрываете дочерний (текущий) VC, родительский VC отображается нормально. Если вы хотите перейти к родителю родителя, просто отклоните родителя, и он отклонит все его дочерние VC. Я не знаю, почему popViewControllerAnimated отлично работает от B до A, но вам не разрешено делать это. Просто используйте dismiss, если вы используете модальные сегы. Никогда не используйте Pop. Поп для толчка. Сделайте это, и все должно работать нормально.

Для перехода из B в A измените свой код на:

[self dismissViewControllerAnimated:YES completion:nil];

Для возврата из C в A используйте этот код:

[[self parentViewController] dismissViewControllerAnimated:YES completion:nil];

ИЛИ ЖЕ

[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];

ОБНОВЛЕНИЕ 2

Я обнаружил, что для сегментов STORYBOARD нам нужно использовать этот код, чтобы вернуться

[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:NO completion:nil];

Этот код прекрасно переходит с C на A и viewWillAppear называется НО viewWillAppear вызывается как в А и В

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

  1. Придерживайтесь этой версии, но она не надежна.
  2. Продолжайте использовать раскадровку, но для использования кнопки backCtoA соединитесь с A из VC C, чтобы она всегда зацикливалась, но загружалась снова каждый раз. Плохо, но все еще хорошо.
  3. Наконец, правильное решение - перейти к контроллеру навигации (кстати, вы можете скрыть панель навигации, если хотите) и иметь стек VC, чтобы вы могли легко использовать popToViewController.
Другие вопросы по тегам