How can I know when the "Back" button was pressed? - objective-c

I use storyboard with identifier, when i want to call some view, I use this code:
ViewB *view = [self.storyboard instantiateViewControllerWithIdentifier:#"View2"];
[self.navigationController pushViewController: view animated:YES];
But I want to do something when i pressed the back button, How can I know that happens this ?

That depends on what you are really up to.
First of all you cannot directly catch such an event or so. Unless you replace the back button with your own back button, assign yours to an action of yours and go from there. Within this action you can perform what ever you want to do. And you will have to care for calling popViewControllerAnimated: yourself.
If you don't really need to know that the button was pressed and just need to react when ever the view controller or its view respectively disappears then you can overwrite viewWillDisappear or viewDidDisappear. But be aware that these methods are called too every time when another view is pushed ontop of your very view.
viewWillUnload or viewDidUnload is probably more what you are looking for.
However, dealloc is called when the view controller is destroyed.
One of these will do depending on what you really need.

Related

Dismiss modal segue

I am trying to understand modal vs push segue and read few Q & A like this and this. One point I am confused from these answers is "The presenter should take care of dismissing the VC it presented."
For example, the example I am writing shows UIPageViewController something like the example available here, with a button at bottom of the page with name "Skip".
In story board I have created a segue (of type Modal) from "Skip" button to another "View Controller" (let us say LoginViewController), but where do I need to dismiss the UIPageViewContoller (if at all required) and how?
EDIT:
After little bit more reading, it seems UIPageViewController (Which has Skip button) should take care of dismissing LoginViewController (because UIPageViewController is the presenter).
In my case, after Login complete, I would like to navigate to "Menu" page, then how can I ask UIPageViewController to dismiss the "LoginViewController" and move to MenuController? I couldn't find any example on how this works.Any help would be appreciated!
As per the tutorial link you have given in question.
There is a APPViewController which is root for the UIPageViewController and also in AppDelegate, so on top of that view, require a Skip button which is above all the subViews in AppViewController. So its IBAction event will be in AppViewController only.
Now first change your AppDelegate self.window.rootViewController to LoginViewController.
In LoginViewController viewDidLoad event, presentModal UIPageViewController.
Now in its action event of skip button, you can write like this:
[self dismissViewControllerAnimated:YES completion:nil];
So it will automatically dismiss all your AppChildViewControllers, and will display LoginViewController, which is already behind.
This is just a base logic to achieve your goal, you might require to change code as per your project implementation.
Hope this helps.
First dismiss the UIPageViewController and then using delegate or block methods (whatever suitable) to get notified when you press the skip button in the parent controller and then calling LoginViewController.

Determine if viewcontroller is already on stack and if so, go to or dismiss it

I have an app I am working on that has a main screen with two buttons. One will take you to a view of a GPS (map) and then once there (new VC) it has options for setting that position or bringing up a list (tableview, another VC) of all locations already tagged.
At the list VC, if you click on the table cell, it will bring up the VC with the map. Problem is, this then adds the same VC bak on the stack. If a user clicks the Cancel button, they go back ones screen, then cancel goes back another screen, etc... until back to the main.
I know I can do the [self.navigationController popToRootViewControllerAnimated:YES]; to pop back to root but that is not always what I want.
Also, I know I can do: [[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];
I guess what I am saying is I want to "reuse" the GPS map view so I can call it from other VC's, so that is why I didn't go with the "pass back" to calling VC. So, is there away to either when a button is pressed and is to present a new VC, can I dismiss the prior one after the new one is shown? This way, a dismiss of current VC would take me back to where I need to be.
I hope makes sense and also that this question doesn't fall into the "Not an actual question" category.
Any help or better suggestions is greatly appreciated. Thx
Geo...
If you want to jump back some number of levels in a navigation controller's VC stack, you'll probably want to use its popToViewController:animated: method. To figure out if a particular view controller is on that stack, look at the navigation controller's viewControllers property. Be careful, though, as this kind of jumping around is a rather nonstandard UI behavior (even though there's API for it) which might confuse your users.
Also, using navigation controllers and presenting modally aren't the only ways to manage multiple view controllers -- you can always set the window's rootViewController yourself (and animate the change with UIView animations), even wrapping up your custom transition type in a custom UIStoryboardSegue if you like.
You can put a delegate in the table view. So that when a cell is pressed the info is passed to the delegate method in the VC which will dismiss the table view and reloads itself with the new info. You will have to implement refresh method in that VC.

UIViewControllers problems

Hi there and thank you in advice for your help. I have a really strange problem while working with ViewControllers in Xcode4. First of all I have to say that I'm not using storyboards and I prefer to create any UI element programmatically. So I've set a UIButton and I want that, when pressed, it brings me to a new view controller. This is the code I'm using for a button:
-(void)settingsAndExportHandle:(UIButton *)buttonSender {
SettingsViewController* settingView = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
settingView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:settingView animated:YES];
}
This buttons is initialized and allocated in the viewDidLoad method of the RootViewController. I want to switch to the other view controller (in this case SettingsViewController) when I press the button.
The strange thing is that when I press the button, the animation that flips the controllers goes well, but when it finishes I obtain the EXACT same things that I had on the RootViewControllers (same custom views, same buttons, same all!). The question is: what I'm missing?? I have to say that I use ARC (automatic reference counting) so I can't release or dealloc the views and buttons I've created on my RootViewController.
Any help will be appreciated. Thank you all!
Pushing and and modally presenting view controllers does not deallocate the view controller that presented them. It simply adds the additional view controller to the stack. You'll need to implement a callback method so that when the user hits the button to flip back to root view controller, your settings view controller lets the root view controller know what's about to happen so you can call a method you've written to reset the interface back to whatever state you need it at. You may also be able to use viewWillAppear: but that's a little messy.
However, according to the Apple Human Interface Guidelines, the user expects that when they push a view controller or modally present it, the view controller they were on will save state and be exactly the way they left it when they came back. It's disconcerting and annoying when state is not preserved while in a navigation controller context. It is especially annoying when it's modally presented.
Think about this - A user is in a hypothetical Mail app. They start typing out an email and set a font size and a color. They tap on the add attachment button, which brings up a modal view controller that allows them to select a picture. They select the picture and the modal view is dismissed, and in your implementation, the mail composing interface would have reset and the email content would be gone or at the very least the selected font size and color would be back to the default. That's not a good experience.

tabBarController and first Tab viewDidLoad

I have created a tabBarNavigated Application. In second tab, I do something that works fine, but now I want to do something in the first Tab, so first I try to NSLog a string, but I get no reaction.
- (void)viewDidLoad
{
NSLog(#"Test");
}
If I add a label to the view, it will be displayed, but no reaction on my code.
if I start my app, i see this view, but i can't call any actions in this method, even if i change the tab, and go back to the first one, still no logs.
I try to NSlog in GehaltView
this is the mainWindow
viewWillAppear dosn't work :(
The -viewDidLoad method is only called when your view is loaded. This method will not be called again unless the view gets unloaded, in which case -viewDidUnload will be called. A view can be unloaded if there is a memory issue, but otherwise they generally stick around.
If you want to trigger an action that happens every time the view appears, then you can use the -viewWillAppear: method instead. This method is called every time the view re-appears. You can track when the view disappears with -viewWillDisappear, and watch the two get called as you toggle between the two tabs.
Note also that -viewDidLoad may get called before the view appears, but -viewWillAppear will only be called when the view actually appears (or moments before, as the will indicates).
EDIT: The code should read
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"View Will Appear");
}
EDIT: This entire answer assumes that you have a subclass of UIViewController. It seems to me that you are by-passing using viewControllers, which in general is a bad idea.
I found the solution, in interface builder i have to add a custom class to the forst tab.

Show UIAlertView in viewDidDisappear: buttons not reacting?

In viewDidDisappear: of a modally presented controller I added a callback to inform who ever is interested about the view being gone (after the animation has finished) without requiring subclassing.
One of my controllers that registered for the callback is firing up a UIAlertView in there. However, once the alert is shown, its buttons don't react.
Another one is adding a subview to itself and again: the buttons of the view don't react.
The resposible handlers of the buttons are not triggered.
I assume it has to do with the fact that viewDidDisappear: is not really finished yet when it call my callback. But even if I used subclassing instead, it would be the same situation.
One explanation could be that there is still some other view covering my buttons because the clicks just don't come through.
So: Can somebody confirm that it is NOT a good idea to do what I am doing (showing an alert, adding a subview in viewDidDisappear), because then I will have to change the flow. If it should be okay, I have to figure out what else is causing this effect.
I'd put the callback into viewWillDisappear: instead. At least then the original UIView reference is still around.
Better solution would be to dismiss the modal view through the parent controller by adding the caller as a delegate. The delegate would implement a protocol to dismiss the modal controller. Call the delegate protocol from the modal view, when you are ready to dismiss.
To avoid changing the flow, you could schedule a timer to show the alert, this will give a chance to the view controller code to complete