For one of my view controller (extends UITableViewController), I need to configure its back button text to "Back". But the back button still shows up with parent view controller's title (the default).
- (void)viewDidLoad
{
...
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
}
You need to set the back button on the view controller that pushed the class onto the stack e.g. the controller that created and pushed the class you are showing
The docs for View Controller Programming Guide for iOS suggest that the UINavigationItems are kept in the Navigation Item Stack which provides the title and buttons for the current item on the stack.
Importantly (I added bits in [])
Although most of the navigation bar’s content is obtained from the topmost navigation item [in the navigation stack], a pointer to the back item [of the previous item in the stack] is maintained so that a back button (with the title of the preceding item) can be created.
Looking at the docs under the Configuring the Navigation Item Object section there is a diagram which shows the stack and the backItem pointing to the item below the top item in the stack. In your case the top item in the stack would refer to the UINavigationItem for the class you are showing and the backItem will be a pointer to the class that pushed it.
NB
Look at that section in the docs an image is worth a thousand words
Try this:
UIButton* backButton = [UIButton buttonWithType:101];
[backButton addTarget:self action:#selector(popView:) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backItem;
self.navigationItem.backBarButtonItem.enabled = NO;
self.navigationItem.leftBarButtonItem.enabled = YES;
[backButton release];
You need implement a simple method popView, something like this:
-(IBAction)popView:(id)sender
{
[self.navigationController popViewControllerAnimated:NO];
}
Here's a bit more information from the latest UINavigationController class reference, which tells you how to change the button in either the "pushing" or "pushed" controller (I'd add the link, but Apple keeps moving stuff around in subtle ways. Please use your favorite search engine).
In summary: if you are configuring the back button in the pushing (ie, the previous) controller, you access the backBarButtonItem. This perfect for configuring a consistently named back button regardless of the next controller's type. If you want/need to change it in the pushed (ie, the current) controller, you need to access the leftBarButtonItem.
The relevant text is here:
The bar button item on the left side of the navigation bar allows for
navigation back to the previous view controller on the navigation
stack. The navigation controller updates the left side of the
navigation bar as follows:
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.
If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the
value of the title property of the previous view controller—that is,
the view controller one level down on the stack. (If there is only one
view controller on the navigation stack, no back button is displayed.)
Related
i have a view controller, which is standalone and has two left UIBarButtonItem, however when i push it, i want to have these two buttons + the back button
i tried
- (void)viewDidLoad
{
[super viewDidLoad];
// back
if (self.navigationController.navigationItem.backBarButtonItem) {
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:self.navigationController.navigationItem.backBarButtonItem, self.barButtonFilter, self.barButtonFilterContacts, nil];
} else {
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:self.barButtonFilter, self.barButtonFilterContacts, nil];
}
}
if there is a back button, than add, else replace
but i didnt work
I am not able to get your problem but according to your caption you want to replace you back button of UINavigationController with a bar button item, in that case you simply need to have a custom button in place of back Button:
UIBarButtonItem *backButton= [[UIBarButtonItem alloc] initWithTitle:#"yourTitle" style:UIBarButtonItemStylePlain target:self action:#selector(someFunction:)];
self.navigationItem.rightBarButtonItem = backButton;
[backButtonrelease];
If this is not your problem please elaborate.
So the issue here is that a UINavigationBar can only have one leftButtonItem and one rightButtonItem. But What you can do is in the center of the UINavigationBar you can have a UIView. You can use this to place the buttons on.
Someone has the code here: adding-buttons-to-the-titleview-of-navigationbar-without-having-to-repeat-code
From Apple's iOS Human Interface Guidelines:
Use a toolbar instead of a navigation bar if you need to offer a
larger set of controls, or you do not need to enable navigation.
Avoid crowding a navigation bar with additional controls, even if
there appears to be enough space. The navigation bar should contain no
more than a view’s current title, the back button, and one control
that manages the view’s contents. If, instead, you use a segmented
control in the navigation bar, the bar should not display a title and
it should not contain any controls other than the segmented control.
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/UIElementGuidelines/UIElementGuidelines.html
I drag out a toolbaritem in storyboard and set it on my nav controller, but when I run my code it's not there, is there something I'm missing?
EDIT:
Tried setting it in code as well in my viewDidLoad method:
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Map" style:UIBarButtonItemStyleBordered target:self action:#selector(viewMap)];
self.navigationItem.rightBarButtonItem = rightBarButton;
Won't work either.
Here's how it's set up in my storyboard:
UPDATE:
Just found my problem. In my controller code when I update it's contents I change the right bar button item for a spinner and never set it back to what it had before.
UINavigationController already has a toolbar built in. It has a property toolBarHidden which is set to YES by default, which is why it is not normally seen. If you are using storyboard you can easily make the built-in bottom toolbar visible by checking the checkbox "Shows Toolbar" in the inspector when the Navigation Controller is selected.
See the UINavigationController documentation here for more details.
EDIT:
Ok, it sounds like what you are trying to do is add a right button to your view controller's UINavigationItem. To do this in storyboard, drag a "Bar Button Item" from the Objects Library onto the Navigation Item in your ViewController. You can then set the title/style/etc of the bar button item. If nothing still shows up when you run your app, make sure that your ViewController is connected properly with a segue to the navigation controller.
Also make sure you are adding the Bar Button Item to your view controller's Navigation Item, NOT to the View Controller itself. Here is how the setup should look in your storyboard:
To add an item to a navigation bar, you need to add a Bar Button Item to the Navigation Item contained in the view controller. Go to your storyboard, find the right VC, and find the navigation item (it's in the hierarchy shown in the navigation controller 'scene'). Just drag a Bar Button Item into that hierarchy underneath the nav item, or directly onto the navbar in the visual builder display.
The navigation controller only looks at your VC's nav item when that VC is pushed onto the stack; hence modifying the VC's nav item in viewDidLoad has no effect.
(I've done this programmatically before but I don't have the code with me, so maybe I'll add that later...)
I have a UITableViewController. When I click on a cell I want to push a new view. This works fine, but the new view doesn't have a back button. Why is this?
TableViewCode:
if([[NSUserDefaults standardUserDefaults] boolForKey:#"isLoggedIn"])
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
ProfileViewController* profileViewController = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profileViewController.message = [NSDictionary dictionaryWithObjectsAndKeys:cell.textLabel.text, #"user_login", #"default", #"message_source", nil];
switch(indexPath.row) {
case kUsernameRow:
[self.navigationController pushViewController:profileViewController animated:YES];
[profileViewController release];
break;
case kAboutRow:
break;
case kTOSRow:
break;
}
}
If your table view controller is created from nib, its default title is #"" (notice: not nil, but an empty string).
Back button has a bug where it doesn't display if title of previous controller on navigation stack is an empty string, so inside your table view controller, you need to set title to either nil or some string in code, or some string in Interface Builder (can't set it to nil there afaik).
From Apple documentation:
The bar button item on the left side of the navigation bar allows for navigation back to the previous view controller on the navigation stack. The navigation controller updates the left side of the navigation bar as follows:
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.
If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the value of the title property of the previous view controller—that is, the view controller one level down on the stack. (If there is only one view controller on the navigation stack, no back button is displayed.)
Check if your Navigation controller has navigation bar enabled. Click on Navigation bar under Navigation Controller in IB and check if 'hidden' is un-ticked. If it is ticked, the navigation bar will not be shown and so the back button would be invisible too.
I've created a UIViewController subclass called addItemToListViewController. I selected add an "xib" as well, and just created a simple page with a couple of labels and a textField. In the interface builder I selected "Top Bar - Navigation Bar" so that when it is put on the stack when the application runs it will have a top bar that will match the initial main window. In the Interface builder it shows the top border, but when I run the application in the simulator the top bar is not present once the view is displayed.
Here is the code I placed in the rootViewController to present the view controller
- (IBAction)addButtonPressed:(id)sender
{
AddItemToListViewController *addItemToListViewController = [[AddItemToListViewController alloc] initWithNibName: #"AddItemToListViewController" bundle:nil];
[self presentModalViewController: AddItemToListViewController animated: YES];
[AddItemToListViewController release];
}
I'm only able to have the top bar present if I manually add a Navigation bar to the xib. If I must add a Navigation bar to my xib, what is the purpose of the "Top Bar" attribute?
- (IBAction)addButtonPressed:(id)sender
{
AddItemToListViewController *addItemToListViewController = [[AddItemToListViewController alloc] initWithNibName: #"AddItemToListViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addItemToListViewController];
[self presentModalViewController: navController animated: YES];
[AddItemToListViewController release];
[navController release];
}
That "top bar - Navigation bar" in InterfaceBuilder is what's known as a "Simulated Metric". It's there to help you lay out your view with correct spacing when other visual elements - the status bar, navigation bar, or tab bar - might consume some of the device's screen real estate. It doesn't actually do anything other than shrink the vertical dimensions of the view defined by the NIB. The purpose is to help you layout your view, not to actually create a component that will appear in your app.
If you want a navigation bar, then you have two choices. The first choice is to use a navigation controller (of which your initial view will have to be the root) and call
[self.navigationController pushViewController:newVC animated:YES];
The process of setting up a navigation controller correctly, etc, is nontrivial, and you should do some searching to find the best way to do that for your app. For a simple app, especially if you're just learning iOS, you can use the "Navigation-based Application" template when you create a new project. With a navcon, you get all the fancy behavior normally associated with that top bar - an automatic back button, fancy left/right scrolling when you transition to a detail view, etc.
The second option is to put a "fake" navigation bar in the detail view, using the Navigation Bar object. You can find that object, plus some other related objects, in the bottom half of the "Utilities View" (the right-most pane) in XCode. Just drag the object into your XIB and blammo, you have a 44-pixel tall gray bar. This navigation bar is just like what you get when you use a Navigation Controller except you don't get the stack functionality; you can still add buttons to the left and right, change the title, tint it to a specific color, etc.
The xib does not know you will use the controller as a modal view as it could also be used for a normal view which could show a top bar. Only when you push the view it will use or ignore the showing of this top bar.
In short: its there in case you will use the xib for a normal view :)
I have a splitViewContller with detailView, which is a NavigationController and delegate for SplitView.
In this NavigationController, I store the "barButtonItem" and "popoverController" arguments, that I get from the method:
splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
like this:
self.barButtonItemVsebine = barButtonItem;
self.popoverController = pc;
Then, I want to display the "barButtonItem" inside a toolbar of a view, that is loaded inside the navigation view - just setting the items of toolbar:
[items addObject:pd.detailViewController.barButtonItemVsebine];
The problem is: when there are many views in the viewControllers stack of navigationController and I call popToRootViewController the "barButtonItem" doesn't show in the toolbar of the rootViewController.
I also tried to reload all buttons in the toolbar.items array every time I pop a view controller, but sometimes the button shows up, and sometimes not. All other buttons, that I create programmatically show up correctly.