Saturday, February 5, 2011

UINavigationController intercepting – popViewControllerAnimated:

So the the problem is that when someone touches the back button on the UINavigationControler, I would like to run some code to update the datasource.

The problem is that i cant seem to find the right delegate to do it. only these are available on the nav controller delegate, and i want the 'didfinishshowing' type method.

– navigationController:willShowViewController:animated:  optional method  
– navigationController:didShowViewController:animated:  optional method

The next best place i thought was the nav bar but when i try that.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot manually set the delegate on a UINavigationBar managed by a controller

This makes sense retrospectively, as you don't want some hacker messing around with the internals of the nav controller and stopping it from working.

This must is a common problem, and i have missed something simple.

  • Add your refresh code to the viewWillAppear:(BOOL)animated method on the view controller that is about to be displayed. In your case, that is the view controller that's already on the navigation stack.

    From dmercredi
  • Just so we're clear: view A is the starting point. User taps something and you slide right to view B. User taps the back button and you're going from B back to A and you want to do something as a result of the 'back' action.

    There are three ways to do it (and on neither do you have to go near the navigationController -- these apply to the underlying viewControllers themselves):

    • As dmercredi suggests override viewWillAppear on view controller A so when you're heading back to it, it refreshes itself. Problem is that viewWillAppear is also called when A is called the very first time. So you'll have to set some sort of flag to distinguish between the first viewWillAppear and any subsequent ones when returning from B.

    • Override viewWillDisappear on view controller B and do your refreshing there. This will only get called when B is about to go away. If there's something on B that goes one level deeper or brings up a modal dialog on top, viewWillDisappear is going to get called so again you'll have to distinguish between the coming and the going.

    • Decouple the various views and use the delegate pattern. View controller A sets itself as a delegate of B and when B updates something it invokes the delegate method, so A is notified of the change and can update whatever it needs to. You can invoke the delegate method any time the user makes a change inside B or override viewWillDisappear and just do it one time on the way out.

    From Ramin

0 comments:

Post a Comment