6

I'm implementing my own 'back' button. Where onClick, the following code is executed in the ViewController (VC) being dismissed:

  1. Dismiss current VC (VC#1)
  2. Pop current VC (VC#1) off my custom navigationStack
  3. Get the last VC (VC#2) from the navigationStack, and present it using

presentViewController

What happens is the back works visually works - i.e. current VC disappears, previous VC appears. However, the viewDidLoad method is not called. So the screen isn't updated with data updates from viewDidLoad.

 [self dismissCurrentViewController:self completion:^{
    [TWStatus dismiss];
    FHBaseViewController *vcToDisplay = [[FHDataManager sharedInstance] popNavigationStack];
    [vcToDisplay.homeVC presentViewController:vcToDisplay animated:NO completion: ^{ }];
}];

Questions:

  1. I was under the impression that viewDidLoad always gets called when presentViuewController is used??
  2. I 'build' the screen using a method called ONLY from viewDidLoad in VC#2. How is iOS displaying the screen without coming into viewDidLoad?

btw, I'm not using storyboards. Any help is appreciated!

Kanan Vora
  • 2,094
  • 1
  • 15
  • 26
snowbound
  • 1,472
  • 2
  • 17
  • 27

2 Answers2

5

My guess is that viewWillAppear is being called but viewDidLoad is not, at least not when you expect it is. viewDidLoad should be called once, but depending on how you're managing the view controllers, viewDidLoad may not be triggered every time your view appears (which happens after loading).

The completion handler is called after the viewDidAppear: method is called on the presented view controller. from presentViewController doc

so put this in your code with a breakpoint on the call to super and verify it is getting called when this transition occurs.

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

edit: since you verified that viewWillAppear is getting called, then I would say that it's coming down to how you are managing the view controller life cycle. Even with a standard UINavigationController, viewDidLoad is not called when a view is shown as a result of popping items on the navigation stack. I would move your logic to viewWillAppear if you are dead set on not using UINavigationController

mckeejm
  • 2,732
  • 2
  • 18
  • 27
  • Thanks @mckeejm. viewWillAppear works. What I found is that presentingViewController won't call viewDidLoad (because it's already in memory). It's when objects are created (via init, new, or copy) that viewDidLoad is made. I've moved my code to viewWillAppear :D – snowbound Jul 28 '14 at 23:04
  • minor point of order, just doing `[[alloc] init]` on a view controller will not cause viewDidLoad to be called. I see this happen often in tests. We typically use a trick in the Cedar testing framework `viewController.view should_not be_nil` that causes the view to be lazily instansiated and viewDidLoad to fire. However if you are using `initWithNibName`, `viewDidload` should be called for you. – mckeejm Jul 29 '14 at 02:38
  • Hey @mckeejm. Could you explain what `viewController.view should_not be_nil` means please? btw, I'm running all of the visuals by code, no nib or interface builder. Thanks! – snowbound Jul 29 '14 at 04:05
  • 1
    it's slightly off-topic , but it's related to a specific testing framework https://github.com/pivotal/cedar. It's a shortcut you can use in that testing framework to trigger those events for use in unit tests. I think the point I was more trying to make is that a plain `[[alloc] init]` style initializer won't necessarily inflate the `view` property of the controller. When you use `[[alloc] initWithNibName]` it will try to inflate the `view` property automatically. – mckeejm Jul 29 '14 at 04:10
  • since you're not using nibs, my comment isn't really relevant though – mckeejm Jul 29 '14 at 04:12
1

When I make a back button pragmatically I use:

[self.navigationController popViewControllerAnimated:YES];

This will invoke the viewDidLoad method. Use that instead of your current code.

Wyetro
  • 7,986
  • 9
  • 42
  • 61
  • This doesn't work for me. Because I don't use a navigationController to load my views :( – snowbound Jul 28 '14 at 02:51
  • Oh well, if you had been that would work. I would take a look at mckeejm's answer, that seems like it should work. – Wyetro Jul 28 '14 at 03:00
  • Want to comment after getting a downvote on this last week (6.5 years after this answer). This answer is incorrect. `viewDidLoad` is not called when popping back to a view controller. `viewWillAppear` is called whenever the view controller appears, while `viewDidLoad` is only called the first time the view controller loads. – Wyetro Jan 19 '21 at 20:22