Here is my code for calling a new view controller that is wrapped in a UINavigationController. I want a simple back button on the restaurantResults controller. My selector does not seem to work. I've tried using pop commands. Will those work since I am using presentViewController and not any sort of push?
Pretty sure my selector is wrong right now because it says self.navigationController, which can't possibly be right.
Here is where I call the new view controllers and set up the back button:
- (void)searchBarSearchButtonClicked:(UISearchBar *)foodNearSearchBar
{
restaurantsViewController *restaurantResults = [[restaurantsViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:restaurantResults];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:nil
action:#selector(backPressed:)];
restaurantResults.navigationItem.leftBarButtonItem = backButton;
[self presentViewController:navController animated:YES completion:Nil];
}
Here is my selector:
-(void)backPressed: (id)sender
{
[self.navigationController popViewControllerAnimated: YES]; // or popToRoot... if required.
}
I also tried:
- (void)backPressed:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
};
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:nil
ction:#selector(backPressed:)];
restaurantResults.navigationItem.leftBarButtonItem = backButton;
these code should be used on the restaurantsViewController;
the target is self.
If you are using a UINavigationController and you want the default iOS back button, you do not need to set it programatically. There is literally nothing to add, it's built in by default.
By pushing the UIViewController into the navigation controller, it'll be in the navigation controller stack of controllers, and iOS will therefore add a navigation bar, and a back button when you dig into the navigation stack.
If its not working, check the following :
That the controller you're pushing from is the root of the UINavigationController. You can set this by code or in storyboard. (you're OK)
That you're pushing from the navigation controller and not the viewcontroller. Essentially you have to do navigationcontroller.push() and not self.push(), otherwise it just won't work. (depends what self is here, but I'm pretty sure your mistake is here)
I see that you're using presentViewController which is for modals, its fine if that is your intent, but if you want a navigation stack, why not embed self in a navigation controller in the first place, hide its navigation bar, and then simply push your next controller onto it.
That way you dont have to manually create that back button, and let iOS deal with everything.
If you must do it that way, you can only "dismiss" when you "present", and "pop" when you "push". But I don't have enough information to know why yours does not work. Try a few things and give us more feedback. But from what I see you're going for a more complicated solution than necessary.
Also I would really start with a simple button that says "close" and see if it works that way before trying to embed it in a bar with an item. That way you tackle one problem, and one new concept at a time
//This works - Just did it
//You can create back button in the view you want to see back button -
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Login"
style:UIBarButtonItemStylePlain
target:self
action:#selector(backPressed:)];
self.navigationItem.leftBarButtonItem = backButton;
[self.navigationItem setHidesBackButton:NO];
// And just do dismiss the view controller in the viewcontroller where the back button is - as below-
- (void)backPressed:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
};
Related
Trying to customize my back button in a drilldown navigation controller.
On my one view controller I have an Add button where the code programatically generates a new UIViewController:
- (void)add:(id)sender
{
MyAddViewController *addController = [[MyAddViewController alloc] initWithNibName:#"MyAddViewController" bundle:nil];
[self.navigationController pushViewController:addController animated:YES];
[addController release];
}
This works and when I click the add button it drills down into the new view. Inside the viewDidLoad method of MyAddViewController.m I have:
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
But this isn't working. The back button in the navigation controller remains the title of the previous view's controller on the stack. It seems that line does nothing. Did I miss something?
Thanks
self.navigationItem.backBarButtonItem is for the back button that appears on the view pushed by the view controller. So you need to move that line to the previous view controller.
This will only work on each child after the viewController that has self.navigationItem.backBarButtonItem.
You're confusing the backBarButtonItem and the leftBarButtonItem. From the UINavigationItem docs on backBarButtonItem:
When this item is the back item of the
navigation bar—when it is the next
item below the top item—it may be
represented as a back button on the
navigation bar. Use this property to
specify the back button. The target
and action of the back bar button item
you set should be nil. The default
value is a bar button item displaying
the navigation item’s title.
So, if you were to change:
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
To:
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
I believe you would get the desired effect.
You can't replace the backBarButtonItem, but you can use the leftBarButtonItem to override it. But to get the new button to perform operate the same as the back button, you do need to set the target and action of the new button something like:
- (void)dismissMyView {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:#"Quit" style: UIBarButtonItemStyleBordered
target:self action:#selector(dismissMyView)];
}
If ViewController A push ViewController B meanwhile we want to set the back bar button tittle, we should set "self.navigationItem.backBarButtonItem = ..".if it was set in ViewController B, it will not work as we want.
My App has a lot going on with it, lol. On my Main Menu, if you click "Chat", it will take you to the Chat XIB.
If you look to the top left in the Navigation Bar I have something called "Main Menu". I want this to take me back to the Main Menu. My Main Menu is on the main.Storyboard. The Chat is an XIB. Both Views have Tab Bars. I've been going in circles all day trying to figure this out. This is the last thing I have tried which crashes:
-(void)MainMenu
{
MainMenuTabBarControllerViewController *MMTBC = [[MainMenuTabBarControllerViewController alloc]init];
[self.navigationController popToViewController:MMTBC animated:YES];
}
- (void)viewDidLoad
//-------------------------------------------------------------------------------------------------------------------------------------------------
{
[super viewDidLoad];
self.title = #"Group";
//---------------------------------------------------------------------------------------------------------------------------------------------
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"New" style:UIBarButtonItemStylePlain target:self
action:#selector(actionNew)];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Main Menu" style:UIBarButtonItemStyleBordered target:self action:#selector(MainMenu)];
//---------------------------------------------------------------------------------------------------------------------------------------------
self.tableView.tableFooterView = [[UIView alloc] init];
//---------------------------------------------------------------------------------------------------------------------------------------------
chatrooms = [[NSMutableArray alloc] init];
}
Since you have two tab bar controllers in your application. I don't think it is a good idea to use navigation controller (push/pop) to manage the transition between them. Try with presentViewController.
When the chat button is pressed, show the second tab view controller.
- (IBAction)chatButtonPressed:(id)sender {
ChatTabBarController *chatTabView = ... // allocate memory and initialize
[self presentViewController:chatTabView animated:YES completion:nil];
}
When the main menu button is pressed, dismiss it.
- (IBAction)mainMenuButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Edit:
Just notice a very similar question being asked a couple of years ago. Take a look at this one:
How can I push tab bar controller after click a button from a view in objective c?
You should use storyboards. Try deleting your XIB and start using an Unwind segue on your storyboard. Are you using push or modal? It changes everything. After you migrate to storyboards, read Apple's docs on Unwind segues.
Best regards,
My UINavigationBar is not handling properly.
I would like it to Navigate back to the last UIViewController, though i get a black screen when pressing the leftBAckButton and not the previous UIViewcontroller.
View
Controller.m viewDidLoad
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:#"&" style:UIBarButtonItemStyleBordered target:self action:#selector(home:)];
self.navigationItem.leftBarButtonItem = newBackButton;
This is the -(void)home:(UIBarButtonItem *)sender
-(void)home:(UIBarButtonItem *)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
Though i feel this is correct i receive this when pressing the button
As you can see the navigationbar seems to disappear and it never navigates to the previous view controller.
When using [self.navigationController popViewControllerAnimated:YES];
I receive! this on the UI
What is causing this and how can i fix it?
I have two UIViewcontrollers, let's call them vcA and vcB in an UINavigationController.
I want vcB to have a custom backbutton that triggers some code, the goal is do some custom animation
In vcA I put this code:
UIViewController *vcB = [UIViewController alloc] init]
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack)];
self.navigationItem.backBarButtonItem = custombackBackButton;
[self.navigationController pushViewController: vcB animated: YES];
Then I added this code both in vcA and vcB:
-(void) handleBack
{
NSlog(#"Going back to vcA");
}
The handleback method is never called. Any hint?
Thanks
Nicola
Dont get me wrong but i think you need to be clear about push pop of UINavigationController.
A navigation controller manages views by pushing/popping them on/off the controller's view stack. When you push an item, the current view slides off screen to the left, and the new view slides over from the right. Ofcourse these animations can be changed according to your wish.
I think This is what you need completely.
Put this in vcA where you want to push vcB from vcA.
UIViewController *vcB = [UIViewController alloc] init];
[self.navigationController pushViewController: vcB animated: NO];
[UIView transitionWithView:self.navigationController.view
duration:0.8
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:nil];
In vcB, you can make a barbuttonitem
UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithTitle:#"BackToVcA"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(addAction:)] autorelease];
self.navigationItem.rightBarButtonItem = addButton;
In addActionMethod: you can put the below code for navigating back with your required animation
- (void)addAction:(id)sender
{
UIViewController *vcA = [UIViewController alloc] init];
[[self retain] autorelease];
[self.navigationController pushViewController: vcA animated: NO];
[UIView transitionWithView:self.navigationController.view duration:0.8 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];
[self.navigationController popViewControllerAnimated:NO];
}
Use trick given by William Jockusch Setting action for Back Button
And also As per the Updating the Navigation Bar
If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the leftBarButtonItem property of the view controller’s navigation item.
If the top-level view controller does not have a custom left bar button item, but the navigation item of the previous view controller has a valid item in its backBarButtonItem property, the navigation bar displays that item.
So if you want to have custom selector You need to write this inside vcB NOT IN vbA
vcB.m
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack)];
self.navigationItem.backBarButtonItem = customBackButton;
}
-(void) handleBack
{
NSlog(#"Going back to vcA");
}
NOTE:
UINavigationController Class Reference
When this navigation item is immediately below the top item in the
stack, the navigation controller derives the back button for the
navigation bar from this navigation item. When this property is nil,
the navigation item uses the value in its title property to create an
appropriate back button. If you want to specify a custom image or
title for the back button, you can assign a custom bar button item
(with your custom title or image) to this property instead. When
configuring your bar button item, do not assign a custom view to it;
the navigation item ignores custom views in the back bar button
anyway.
Here is is mentioned that If you want to specify a custom image or title for the back button, you can assign a custom bar button item (with your custom title or image) but it ignores custom view. So your selector is not invoking.
Your doing mistake. First Push to vcB and in vcB viewDidLoad method put this code.
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(handleBack)];
self.navigationItem.backBarButtonItem = custombackBackButton;
and also put this in vcB:
-(void) handleBack{
NSlog(#"Going back to vcA");
}
you can not modify the backBarButtonItems action , it is do the default (back) action , you should do your custom thing in the leftBarButtonItems
in your vcBs class add this :
- (void)viewWillAppear:(BOOL)animated
{
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack)];
self.navigationItem.leftBarButtonItem = customBackButton;
}
- (void)handleBack
{
NSLog(#"back");
}
I dropped in a UINavigationBar in UIInterfaceBuilder. I present this view modally and just want a UIBackBarButton to return to my last view. I have an outlet and property to this UINavigationBar declared. I thought in my viewDidLoad method, I could create a UIBackButton like this:
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleBordered
target:self
action:#selector(goBack)];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
But I do not see my UIBackBarButtonItem on the UINavigationBar. I think I am doing something wrong here since I don't think my UINavigationBar knows I'm trying to add this UIBackBarButtonItem to it in this way. Would I have to do create an NSArray, put the button in it, and setItems for the NavigationBar instead?
I'm confused on how the navigationItem property works vs the setItems of the UINavigationBar as well. Any help would be appreciated. Thanks!
You are trying to set the Back Button Item in a modal view which doesn't add a backBarButtonItem. This what causes the Button (or any sort of back button for that matter) not to show. The backBarButtonItem is mainly for use with Pushed View Controllers which have a Back Button added from the parent (next item below) when you push a new view controller (top item). The Apple UINavigationItem Documentation says:
When this item is the back item of the navigation bar—when it is the next item below the top item—it may be represented as a back button on the navigation bar. Use this property to specify the back button. The target and action of the back bar button item you set should be nil. The default value is a bar button item displaying the navigation item’s title.
To get the Back Button on the left side like you wish, Try changing
self.navigationItem.backBarButtonItem = backButton;
to
self.navigationItem.leftBarButtonItem = backButton;
making a call such as this from a view controller
{
NextViewController* vcRootView = [[NextViewController alloc] initWithNibName:#"NextView" bundle:[NSBundle mainBundle]];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:vcRootView];
[vcRootView release];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
}
will present NextViewController as a Modal view on the calling view and NextViewController will have a navigationController for it.
In The NextViewController implementation file all you need is this
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self
action:#selector(barButtonBackPressed:)];
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];
}
-(void)barButtonBackPressed:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
to have the back button to dismiss the modalview. Hope it helps.
Use below code snippet :
//Add button to NavigationController
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#“back”, #"")
style:UIBarButtonItemStylePlain
target:self
action:#selector(goBack)];
self.navigationItem.leftBarButtonItem = backButton;
//Perform action on back Button
- (void) goBack { // Go back task over-here
}
Different style types available are :
UIBarButtonItemStylePlain, UIBarButtonItemStyleBordered, UIBarButtonItemStyleDone
You may use this setters without creation new UIBarButtonItem:
[self.navigationItem.leftBarButtonItem setAction:#selector(doBackButton:)];
[self.navigationItem.leftBarButtonItem setTarget:self];