6

In my app, I have about a dozen different view controllers, pushed onto or popped from the stack in different orders. When a view has appeared (I'm using viewDidAppear method) I need to determine whether this is because this view has just been pushed onto the stack or because one of its subviews was popped from the stack.

I went through this question: viewWillDisappear: Determine whether view controller is being popped or is showing a sub-view controller

But I don't think it's helping me very much. Any suggestions please?

Community
  • 1
  • 1
Aleks G
  • 52,841
  • 25
  • 149
  • 233

3 Answers3

4

The best solution, if you can manage it, is to try to revise your code so that it doesn't matter whether the controller was just pushed or its child was just popped. Fundamentally, a view controller mediates between its view and the data that the app operates on. As long as that data is up to date, the controller shouldn't be concerned with what was happening before its view appeared. Tasks that your controller currently does based on the previous state of the app, such as updating the data, might really be better located in a different class.

Another possibility, if you're using storyboards, is to rely on -prepareForSegue:sender: instead of -viewDidAppear. The segue you're passed in that method has properties that identify the source and destination view controllers, and that's usually enough information to tell you how your controller came to be the current one.

If neither of those work in your case, consider moving your configuration code to one or more different methods. The root of the problem you're facing is that -viewWillAppear really doesn't mean what you need it to. Create a method that does mean what you need, like -childControllerFinished, and use that to do the configuration work that you need.

Caleb
  • 120,112
  • 19
  • 171
  • 259
1

What you could do is have a BOOL property on your view controller, called alreadyPushed or something similar. Then in your viewDidAppear method check if it is false (Which it will be the first time the viewDidAppear is called), if it is set it to true.

Then when a subview viewController is popped the viewDidAppear method would check to see if the alreadyPushed property is set to true, if it is you know that a subview has just been popped.

Craig Mellon
  • 5,391
  • 2
  • 18
  • 25
0

If a view controller is pushed onto the stack, it's viewDidLoad method will be called; if it's sub-controller is popped, then viewDidLoad is NOT called.

- (void)viewDidLoad {
    [super viewDidLoad];
    //do any setup you want to do only when the view is pushed onto the
    //stack for the first time; this method will not be called
    //when the view's subview is popped and this one becomes visible
}

So, use viewDidLoad (or initWithNibName, depending on what you're doing) for one-time setup when the view controller is pushed for the first time, and viewDidAppear for setup that you want to do every time the view appears. With the UINavigationController, you might want to implement these two methods in the UINavigationControllerDelegate protocol:

- (void)navigationController:(UINavigationController *)navigationController 
    willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewWillAppear:animated];
    //do any every-time setup *before* the view is shown
}

- (void)navigationController:(UINavigationController *)navigationController 
    didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewDidAppear:animated];
    //do any every-time setup *after* the view is shown
}
eric.mitchell
  • 8,501
  • 12
  • 50
  • 91
  • 5
    Its not safe to assume that `-viewDidLoad` will be called every time a view controller is added to the nav stack. A view controller might be created well in advance of being used, and at some point along the way its view may also be created. That's when `-viewDidLoad` will be called. After that, the view is already loaded, and the method won't be called just because the controller is pushed onto the stack. – Caleb Dec 21 '11 at 16:26
  • Very good point. However, it doesn't sound like that is the case here. The OP didn't mention anything about pre-caching of view controllers. – eric.mitchell Dec 21 '11 at 16:38
  • 1
    @Caleb: that's a very good point, especially in my case. As the view controllers are pushed and popped onto the stack, when I pop a controller, I don't destroy it, but reuse it later when I need to push it again. – Aleks G Dec 21 '11 at 17:03