UINavigationController intercepting – popViewControllerAnimated: - iphone

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.

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.

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.

Related

UITabViewController, viewWillAppear does not invoked?

New to iOS, kindly bare if the question is very basic? When I press the tab button multiple times, it is not invoking viewWillAppear function? If I am wrong, then which function gets invoked, each time a tab button is pressed being on the same tabview?
You are correct, viewWillAppear is a little special, it is usually called automatically but in some cases including when you are adding a view controllers view manually (view addSubview:), and also when adding this as a view controller to a UITabViewController it doesn't get messaged.
This however is only for the root view, as you navigate (maybe with a navigation controller) back and forth, that root view's viewWillAppear will get triggered as some point.
In short, if you need to implement something in viewWillAppear in these cases, you should message it yourself when you know it's going to be presented. You can handle this case in your view controller, check out the following article about the matter:
http://www.touchthatfruit.com/viewwillappear-and-viewdidappear-not-being-ca
Good luck.

iOS: return from pushed ViewController via delegate methods?

I've been wrestling with this for almost 2 hours now and no luck.
I have a View Controller. Lets call it First. I press a button and it takes me to Second view controller using a modal style. In Second I add some data which I can save or discard via two navigation bar buttons: Save and Cancel. both do what they do and then they return me to the previous screen. I implemented a protocol and I use the delegate. So far everything works fine.
Today I decided to have a Third View Controller which can be accessed from the Second VC. The problem is I couldn't move to THIRD until I changed the transition from First to Second to PUSH (instead of modal). Now I can go from First to Second and from Second to Third. All good again.
THE PROBLEM : If I press Cancel or Save on the Second VC, it calls the methods, it uses the delegate to go to FIRST and execute some function but when it calls:
[self dismissViewControllerAnimated:YES completion:nil];
nothing happens and Im stuck on the Second view. Basically I was using MODAL with Delegate and protocol methods... I switched to PUSH, and I cant get rid of my Second view and return to First. It seems like the dismissViewController doesnt do anything.
Any help is greatly appreciated. I can fix all this by removing the cancel button and using the BACK which comes by default with PUSH but I just want to know what the problem is with it.. THANK YOU !!
On your 2nd viewContrller call the UINavigationController's method popViewControllerAnimated: or popToRootViewControllerAnimated:. This will pop the controller (the one calling, which is the 2nd) off the nav stack. You can get the navigation controller in a UIViewController via its property navigationController.

How to tell when a view has become active

I'm using a navigationController to push a new view onto the stack. Once I'm done with that view I pop it. I want the original or root view at the bottom of the stack which then becomes active to know when this has happened to it can call a method on itself
There are two options
1. implement -(void) viewWillAppear:animated: This is often a useful strategy for knowing that a view is about to become visible. If you are always doing the same thing when this happens, then this is quick and easy.
2. Send a NSNotification. This is useful when you want your underlying view to perform some action in response to a particular event happening elsewhere.
Use the viewWillAppear delegate. It is called right before showing the view.

UINavigationController issue. viewWillDisappear/viewDidDisappear of view controllers not call on application startup

I am writing an application(for iPhone) that uses the UINavigationController to show different view via pushViewController. I am trying to push multiple UIViewController immediately upon application startup without user interaction. When an user open up the application, they will be looking on a screen with a navigation bar on the top that already have a back button.
The problem I am experiencing is that viewWillDisappear and viewDidDisappear of a ViewController does not always get call if another ViewController is pushed on top of it immediately upon application start up without user interaction. If the ViewController being pushed on top is activate by the user with a button click, then viewWillDisappear and viewDidDisappear of the view being cover always get call.
Note. viewWillAppear and viewDidAppear of the covered view controller always get called.
In the code that is experiencing the problem, I am pushing the new view controller in viewDidAppear of the previous ViewController.
Anyone know what I might be doing wrong or if the behavior I am seeing is expected?
The problem I am experiencing is that viewWillDisappear and viewDidDisappear of a ViewController does not always get call if another ViewController is pushed on top of it immediately upon application start up without user interaction.
Sound pretty sensible to me. After all, the "covered" view never appeared on screen, so it cannot disappear. I would expect this behavior.

viewWillAppear not getting called for detailView of UISplitViewController

I am experimenting with the splitViewController, introduced for iPads and am stuck at a point. I have a button on my detail view of the splitViewController, clicking on which a modal view opens. Now I want to change the positoning of UI controls on the detail view when the modal view gets dissmissed.
A pretty obvious way of doing this would be to catch the view transition in the ViewWillAppear method of the detailView. But it's not being called in this case. I remember facing the same problem in tabBarController where [tabBarController viewWillAppear:animated] was needed to be set before viewWillAppear of views in each tab item got called. I tried doing this with the splitViewController as well, but this doesn't seem to to work.
Any Ideas??
If the positioning is required due to an action that occurred in the modal view, you should use an explicit delegate callback. That will allow you to clearly specify the control flow and resulting behaviour of your app.
You should then define a protocol that has specific methods that carry pertinent information about the action taken. When the action occurs in the modal, perform the protocol method on the delegate, and it can react to that event (for you it seems to be a re-layout of button positioning).
To get an idea of the methods that are abstract enough to handle generic modal behaviour, look at UIAlertViewDelegate protocol. Here the delegate will get an alertViewCancel: message when the user decides to take no action, or alertView:didDismissWithButtonIndex: when they selected one of the options presented to them.
That is a good start for how to define the protocol.
If you need a many view controllers to react to the action taken in the modal, say a Sign In modal, then a better mechanism is notifications.