I have a view controller in a navigation stack that represents a form that the user can fill out. The form has a handful of text fields and an "Apply" button at the bottom. If the user taps the native back button on the navigation bar after entering some information, I want the user to be prompted with a confirmation message: "Your changes have not been saved. Are you sure you want to go back?" But I'm not sure of a way I can "legally" override the action of the native back button. Is this possible?
In Objective C you can override the navigationShouldPopOnBackButton function of the ViewController class to display a prompt message to the user
-(BOOL) navigationShouldPopOnBackButton {
// Do your logic
return NO;
}
You need to set UINavigationItem to the custom button in you UIViewController class.
After that you can execute your custom code in the backButtonTouch: function:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Back", nil)
style:UIBarButtonItemStyleDone
target:self
action:#selector(backButtonTouch:)];
Related
I am trying to find a way to stop some of the processes within a detail controller (and let the user know that this is happening) when the back button in the navigation bar is pressed. However, I can't find a way to implement these changes when the button is pressed.
Is there a way to do this?
If you want to raise a user alert/notification before going back, you are really going to have to create your own back bar button item and assign it to self.navigationItem.leftBarButtonItem.
You need to hide the default button using:
self.navigationItem.hidesBackButton = YES;
Then add a target to your new button which does your process cleanup and raises an alert. In the alert handler, pop the controller once the user has acknowledged the alert.
The fastest and easiest way is to use custom back button like below;
-(void)viewDidLoad{
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(actionBack)];
[self.navigationItem setBackBarButtonItem:barButtonItem];
}
-(void)actionBack{
//PopViewController
}
Like any other button.
Put this in the .m file.
- (IBAction)saveButton:(id)sender {
//actions
}
Then control drag from the UINavigationBarButton to the IBAction
i have 2 class the first is view controller and another one tableviewcontroller i insert UIBarbuttonItem to insert mew user i want the add button to target to the login page of view controller how can i make that
If I understood your question right, and you want to link the UIBarButtonItem to another ViewController - you can do so simply by ctrl + dragging from the UIBarButtonItem to another ViewController to create a segue between them.
Edit after comment:
Step-by-step:
First, ctrl + drag from your first ViewController to the second to create a segue connection between them
Then, use your code and create a method
Create a method to call the segue:
-(void)myMethod {
[self performSegueWithIdentifier:#"identifier" sender:self];
}
Specify this method like Victor Johnson shows and once myMethod is called, you will be taken to the other ViewController.
If all you're trying to do is switch from one view controller to another, you can ctrl + drag from the first view controller to create a segue between the two controllers, then give the segue a unique identifier (I'll use "SegueIdentifier"). Then in the first view controller create a new method that you can call each time the add button is pressed. Then you can set that as the selector for your add button.
- (void)goToSecondViewController {
[self performSegueWithIdentifier:#"SegueIdentifier" sender:self];
}
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(goToSecondViewController)];
I have fairly simple UINavigationControllers with two screens: screen1 & screen2.
When the user is on screen2 and clicks < Back I want to trigger an event before screen1 is shown -- basically I want to fetch data from the server for screen1.
Is there a way to do this?
In your viewDidLoad do this:
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"icon_back.png"] style:UIBarButtonItemStylePlain target:self action:#selector(goBack:)];
self.navigationItem.leftBarButtonItem = backBarButton;
Implement the method goBack:
- (void)goBack:(id)sender {
//Do something
[self.navigationController popViewControllerAnimated:YES];
}
Hope this helps.. :)
If you're using storyboard, you can handle your back action in.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
Only by doing it in viewWillDisappear. Unfortunately it will be triggered also when you present a new screen over the current one, not just when you tap the back button. You could however add a custom back button, and place your code in it's action method. After the operation is finished, call [self.navigationController popViewControllerAnimated:YES]
-(void)viewWillDisappear:(BOOL)animated{
if (![self.navigationController.viewControllers containsObject:self]) {
NSLog(#"Back Event");
}
}
You can do in two way.
Create custom button and set event.
Check on viewWillDisappear when users pop the screen
In my RecordViewController, within the didSelectRowAtIndexPath I push a detailViewController (which inherits from UIViewController):
[[self navigationController] pushViewController:detailViewController animated:YES];
Once the DetailViewController appears I can see a Back navigationButton in the top left corner, which automatically pops the current view controller to get back to the previous ViewController.
Now I need to show a UIAlertView and ask the user, if the data should be saved or not.
And only when the user has made a decision, the current view controller should disappear.
My problem is if I put this code into viewWillDisappear, it is already too late. I can't stop the process while showing the UIAlertView. This needs to be intercepted the moment the user pressed the back button.
Is there a method I could override to achieve this?
Create a UIBarButtonItem:
UIBarButtonItem * backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: #"Back"
style: UIBarButtonItemStyleDone target: self action: #selector(onBackButtonTapped:)];
Assign it to left bar button item:
self.navigationItem.leftBarButtonItem = backBarButtonItem;
Implement onBackButtonTapped API:
- (void) onBackButtonTapped: (id) sender
{
// Display an UIAlertView
}
You may want to customize the back button. Please look into UIBarButtonItem for more details.
Instead of pushing a detail view controller, the usual way to gather data is to present one modally. That will give you 2 free spaces on the left and right of the (new) navigation bar to place a Save and Cancel button.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[self presentViewController:navigationController animated:YES completion:nil];
// detailViewController will have to set up buttons in its init
You can use a delegate protocol you create to handle save and cancel actions in the presenting (i.e. not the detail) view controller.
Overview: The idea is to have your own barbutton to intercept the backing out from the VC.
In your viewDidLoad you can do this
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleDone target:self action:#selector(Back:)];
self.navigationItem.backBarButtonItem = backButtonItem;
Then your Back: method can do this
-(void)Back:(id) sender
{
//Your code for showing AlertView with delegate as self. Remember to conform to the UIAlertViewDelegate protocol.
}
Then put your save functionality in
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (selected buttonIndex is the one for saving data)
{
//save your data
}
//popViewController
}
I have an edit rightbarbuttonitem in my view in navigation bar. I set it up with the help of storyboard/IB, not programmatically. Now, all i want is to assign an action when the "done" barbuttonitem is pressed (not edit).
Is there a way to achieve it? I tried manually through -(IBAction), but it's not working. Also, i want to perform the action on selected items in UITableView. So if you give me an idea, it would be great.
That button calls the method
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
You can implement it and it will get called everytime your edit/done button gets tapped. All you have to do is check the button's title property to see when it's showing done and when it's showing edit
If you declared your button as an IBOutlet then all you'd need to do is use the synthesised variable on your .m as so:
_yourBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(runMethod)];
self.navigationItem.rightBarButtonItem = _yourBarButton;
Then you'd have to declare your run method:
-(void)runMethod
{
//do stuff
}