3

How can I know when a UIViewController has been just pushed from a UINavigationViewController ?

I obviously don't want to use viewDidAppear because that's method is called everytime that view appears, not just when it's pushed.

viewDidLoad is called before the view controller is pushed and I don't have the reference to the navigationController available

aneuryzm
  • 63,052
  • 100
  • 273
  • 488
  • 1
    from [this diagram](https://rdkw.wordpress.com/2013/02/24/ios-uiviewcontroller-lifecycle/) I don't see other events sent besides the ones you mentioned. You could use `viewDidAppear` with a boolean value like shown [here](http://stackoverflow.com/questions/28207063/how-to-do-some-stuff-in-viewdidappear-only-once) – Lulylulu Apr 14 '16 at 13:05
  • 3
    Have a look at [UIViewController:willMoveToParentViewController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/willMoveToParentViewController:) or the alikes – Tom Knapen Apr 14 '16 at 13:15
  • Unfortunately willMoveToParentViewController is called also when the controller is popped. – aneuryzm Apr 14 '16 at 13:43
  • @Patrick But when popped, the parent parameter will be `nil`. – rmaddy Apr 14 '16 at 14:01
  • @maddy Yes, indeed. It has been discussed in Sulthan answer. – aneuryzm Apr 14 '16 at 14:07

3 Answers3

2

You can check this from of navigation viewcontrollers array

//Eg:
//Maintain your navigation object:
@property (strong, nonatomic) UINavigationController *navController;

//use:
   if([[self.navController.viewControllers lastObject] class] == [your view controoler class]) {
  // your view controller is present in navigation stack
}
Suhas Arvind Patil
  • 1,732
  • 1
  • 19
  • 31
0

There are multiple ways to do this:

  1. The simplest way. When pushing the controller, set a flag on it. You know when you are pushing, you can run custom code at that moment.

  2. UINavigationControllerDelegate and its navigationController:didShowViewController:animated:. Again, you can make the controller the delegate or just call a method on it externally.

  3. Logic inside the controller - You can probably use a combination of viewDidAppear and willMoveToParentViewController:. Initially, when the controller appears, it has been pushed. After that, you can reset the "pushed" state when the controller is removed from the navigation controller when listening to changes of parent controller. Your use case is not very clear but in some cases you could just handle the first viewDidAppear call and it would work.

However, note the first two options are far easier to implement. That's because you are trying to listen to an event from a class that shouldn't know about that event. The most sensible solution in that case is listen to that event somewhere else and setup the controller externally to handle that event.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • 1. Why shouldn't the pushed view controller know when it's pushed? – aneuryzm Apr 14 '16 at 13:37
  • 2. Why do you say "a combination of viewDidAppear and willMoveToParentViewController"? As @TomKnapen commented willMoveToParentViewController is called when the view controller is pushed, therefore solution 3 seems the simplest and most correct to me. – aneuryzm Apr 14 '16 at 13:38
  • @Patrick Because it's not the responsibility of the controller to know how it has been shown. That's the responsibility of the navigation controller or any other container class. – Sulthan Apr 14 '16 at 13:38
  • If it is not its responsibility, what about didAppear and willMoveToParentViewController then? The responsibility should be of the parent controllers in this case too, but still the view controller has these methods. – aneuryzm Apr 14 '16 at 13:40
  • @Patrick `willMoveToParentViewController` will be called also in other situations, e.g. when the controller is `popped`. From your question I wasn't very sure whether you are showing the controller in multiple ways (e.g. pushing at one place, presenting at another place). In that case using `willMoveToParentViewController` would not work because it is not detecting pushing, it is detecting moving to a parent controller. – Sulthan Apr 14 '16 at 13:41
  • Ah I see. willMoveToParentViewController is called also when it's popped indeed. That's not what I want. – aneuryzm Apr 14 '16 at 13:43
  • 2
    @Patrick You might notice that `willMoveToParentViewController` will have a different (`nil`) parameter when the controller is popped so it could actually work in your case. – Sulthan Apr 14 '16 at 13:44
  • I see, indeed. I could use that parameter. – aneuryzm Apr 14 '16 at 13:47
0

You can do that from viewDidAppear. set a flag or bool status to true or YES when pushed from previous VC. and then put condition in viewDidAppear that if status or flag is true then only do some stuff that you want to do on push. when you pop from another view to current view set this flag or status to NO so, your condition from viewDidAppear will not execute.

Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75