1

My UIViewController is in a navigation stack. How can I detect when the user is trying to pop up to a previous level vs. pushing a new view controller over it?

I want to post a notification when the view is removed from the stack, as if the user had tapped a Save button that I don't have.

Steven Fisher
  • 44,462
  • 20
  • 138
  • 192

2 Answers2

3

If you're using a UINavigationController, then UINavigationBarDelegate is the delegate class and it implements the following methods.

Pushing Items

– navigationBar:shouldPushItem:
– navigationBar:didPushItem:

Popping Items

– navigationBar:shouldPopItem:
– navigationBar:didPopItem:

You can put code in these method that you want to be executed when the view is popped from the stack.

PengOne
  • 48,188
  • 17
  • 130
  • 149
  • This looks promising, thanks. (I'll accept once I get a chance to verify.) – Steven Fisher Dec 05 '11 at 23:03
  • 1
    Looks like a good idea, but doesn't work. Assigning a delegate to the UINavigationBar breaks the navigation controller. I guess that's how UINavigationBar interacts with UINavigationController. – Steven Fisher Dec 05 '11 at 23:29
  • @StevenFisher Curious; I managed to get this to work on an app a while back. I'll look for the project and post details. Until then, I found [this related question](http://stackoverflow.com/questions/6413595/uinavigationcontroller-and-uinavigationbardelegate-shouldpopitem-with-monotouc?answertab=votes) which may help you. – PengOne Dec 05 '11 at 23:37
  • The docs for UINavigationBar do indeed say the following: "A navigation controller automatically assigns itself as the delegate of its navigation bar object. Therefore, when using a navigation controller, you must not attempt to assign a custom delegate object to the corresponding navigation bar." But I wonder if you could put your own delegate in the middle and forward the calls to the navigation controller. – Kristopher Johnson Mar 19 '12 at 16:17
2

You could do something in viewWillDisappear: and there is also the UINavigationControllerDelegate protocol that has two methods for detecting when views will or have been shown.

Chris Wagner
  • 20,773
  • 8
  • 74
  • 95
  • 1
    That won't work, it disappears if you pop it off or push something on top of it. – Terry Wilcox Dec 05 '11 at 23:00
  • UINavigationControllerDelegate protocol looks the right way to go. – Steven Fisher Dec 05 '11 at 23:37
  • Agreed that `viewWillDisappear` would be a less than ideal place to do this as it can be called at times that do not make sense to your context. Though you could review the navigation stack within `viewWillDisappear` to see where in the hierarchy your view is located and do the appropriate thing. I think the UINaviationControllerDelegate is a better approach though. – Chris Wagner Dec 05 '11 at 23:43
  • This is looking like it will probably work in `navigationController:didShowViewController`: `id viewControllerStack = [navigationController viewControllers]; if ( [viewControllerStack count] == [_navigationStack count] - 1 ) { ... } _navigationStack = viewControllerStack;` Similar in `willShow`, only don't set `_navigationStack`. Gyrations are necessary because `viewControllers` is already updated by the time the delegate is called. – Steven Fisher Dec 06 '11 at 00:29
  • As a notice, `UINavigationControllerDelegate` doesn't tell you which view controller willHide/didHide. When a new view controller willShow/didShow, the willHide/didHide view controller may already been removed from `navigationController.viewControllers`. – Jonny Feb 19 '19 at 11:26