viewWillAppear not called after popToViewController

浪子不回头ぞ 提交于 2021-01-28 21:39:59

问题


I have a little problem. I am working on a simple application with Views Controllers in a Navigation Controller like this: A->B->C (-> are modal segues) View A is the Root View Controller and I need to come back to A from C. If I call the method popToViewController from B, A run the viewWillAppear; if I call the popToViewController from C (to A), viewWillAppear on A is not called. How can I solve this? (Working on Xcode7 and 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];
}

回答1:


This should be your design:

Controller A -> modal segue to Nav Controller(Controller B is root view controller) -> push segue to controller C.

So if you want to come from C to B, you do a pop.

When you want to come from B to A or from C to A, you do a dismiss.




回答2:


If you implement one of these two CASES provided below you will definitely get viewWillAppear and be sure you wrote it correct with it's super

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

CASE 1 - Using Navigation Controller

If you want to Pop from one ViewController to another you need to have all of them in the same navigation stack. It means every time you want to open new View Controller you need to do something like this:

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

instead of doing this

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

And after that if you already have all VCs in that same Navigation Controller, you can use this code to go one step back (e.g. from B to A, from C to B)

[self.navigationController popViewControllerAnimated:YES];

And you can use this code to jump to the beginning (e.g. from C to A)

[self.navigationController popToRootViewControllerAnimated:YES];


CASE 2 - Usual Cycle (Looks like what you need)
This is en easy case but you need to be more careful with your code. You can just get parent of the parent to Leave current View Controller

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



Note: You can't use navigation controller functions with modal presentation functions. Push is with Pop, Present is with Dismiss


UPDATE 1

Modal segues is creating a nested connection(one line of a tree). If you close child(current) VC parent VC appears normally. If you want to jump to the parent of the parent just dismiss the parent and it will dismiss all it's child VCs. I don't know why popViewControllerAnimated works fine from B to A but you are not allowed to do like that. Just use dismiss if if you are using modal segues. Never use Pop. Pop is for Push. Do this and everything should work fine.

For going back from B to A change your code to:

[self dismissViewControllerAnimated:YES completion:nil];

For going back from C to A use this code:

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

OR

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

UPDATE 2

I discovered that for STORYBOARD segues we NEED to use this code to go back

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

This code totally fine jumps from C to A and viewWillAppear is being called BUT viewWillAppear is being called both in A and B

You have 3 tracks to choose (Actually you have more, like using delegates and notifications but this is too bad)

  1. Stick to this version but it is not reliable.
  2. Keep using storyboard but for using backCtoA button connect with A from VC C so it always loops but loads again every time. Bad but still ok.
  3. Finally the right solution is to move to Navigation Controllers(btw. you can hide Nav Bar if you want) and have VCs Stack so you can easily use popToViewController


来源:https://stackoverflow.com/questions/33268259/viewwillappear-not-called-after-poptoviewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!