UIViewController: setToolbarItems vs navigationItem - iphone

my application has a UIViewController subclass which is being managed by a UINavigationController.
In the viewDidLoad of my UIViewController subclass, I was attempting to add a UIBarButtonItem to the toolbar like this:
settingsButton = [[UIBarButtonItem alloc] initWithTitle:#"Settings"
style:UIBarButtonItemStylePlain target:self action:#selector(viewSettings:)];
[self setToolbarItems:[NSArray arrayWithObject:settingsButton]];
this wasn't working out for me, so after some googling around, I tried this:
[[self navigationItem] setRightBarButtonItem:settingsButton];
which worked out fine. from reading the UIViewController documentation, I'm still confused about why setToolbarItems wasn't working. I verified in the debugger that the button was in the toolbarItems array in the viewDidAppear method. the button itself just wasn't appearing on my toolbar.
so, my question is, why didn't setToolbarItems work for me in the first code snippet?
I don't have the toolbar configured in my xib for this view controller at all, if that makes a difference.

Yes that make the difference.Whenever you see a bar on view by default for navigation based apps that is not a toolBar actually that is , navigation bar.so you can add item by referencing self.navigationItem.

[self setToolbarItems:[NSArray arrayWithObject:settingsButton]]; essentially populates the navigation controller's bottom toolbar - not the Left and Right top bar buttons.
The bottom toolbar is, by default, not displayed. To display it you must call [self.navigationController setToolbarHidden:NO]
Below is the relevant documentation - UINavigationController Class Reference
toolbar:
The custom toolbar associated with the navigation controller.
(read-only)
#property(nonatomic,readonly) UIToolbar *toolbar Discussion This
property contains a reference to the built-in toolbar managed by the
navigation controller. Access to this toolbar is provided solely for
clients that want to present an action sheet from the toolbar. You
should not modify the UIToolbar object directly.
Management of this toolbar’s contents is done through the custom view
controllers associated with this navigation controller. For each view
controller on the navigation stack, you can assign a custom set of
toolbar items using the setToolbarItems:animated: method of
UIViewController.
The visibility of this toolbar is controlled by the toolbarHidden
property. The toolbar also obeys the hidesBottomBarWhenPushed property
of the currently visible view controller and hides and shows itself
automatically as needed.

try to use
[toolbar setItems:[NSArray arrayWithObject:settingsButton] animated:YES];
instad of :
[self setToolbarItems:[NSArray arrayWithObject:settingsButton]];
shani

On ipad apps, you've got to set toolbar items to the "topViewController" (yes this is counter-intuitive).
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:catView];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:#"item 1" style:UIBarButtonItemStylePlain target:nil action:nil];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:#"item 2" style:UIBarButtonItemStylePlain target:nil action:nil];
[nav setToolbarHidden:NO animated:YES];
// WRONG: [nav setToolbarItems:[NSArray arrayWithObjects:addButton, nil]];
// CORRECT (for ipad apps):
[nav.topViewController setToolbarItems:[NSArray arrayWithObjects:item1, item2, nil] animated:NO];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:nav];

Related

How can I change back button's text on appdelegate

I have navigationController and I want to change nav back button text on appdelegate. so I want to change every uiviewController's back button's text on appdelegate. Is it possible?
I wrote the following code but it's not working.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
navigationController=[[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
self.navigationController.navigationItem.backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"custom back text"
style:UIBarButtonItemStyleBordered
target:nil
action:nil]; // didn't work
[self.window makeKeyAndVisible];
return YES;
}
You need to understand the difference between the navigation bar (there is one, owned, managed and controlled by the navigation controller) and the navigation items (there are many, one per view controller in the navigation controllers stack, owned and controlled by the view controllers). So you can't change it from where you are trying.
Instead, change it in each view controller or subclass the navigation controller (or act as its delegate) so you can change each view controller as its added to the stack.
Just adding to the answer that appeared while I was typing.
For example:
UIViewController *viewController = [[UIViewController alloc] init];
viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"custom back text"
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
[self.navigationController pushViewController:viewController];
But be careful. WIth this you're now responsible for handling the button action and this one here will do nothing.

iPhone toolbar for entire app

I have my app base on navigationController. So i set the toolbar visible for some views and for others i didnt calling setToolbarHidden:NO or YES.
first question, this goes in viewWillAppear method ?
Then in my appDelegate, I put one item on the toolbar but is not being show.
can someone show me how can I use delegate protocol here so each view know what to do when a item is pressed??
my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//create itemViewcontroller
EventosViewController *itemsViewController = [[EventosViewController alloc] init];
//create UINavigationcontroller, stack only contains itemviewcontroller
navController=[[UINavigationController alloc] initWithRootViewController:itemsViewController];
//navController will retain itemviewcontroller, we can release it
[itemsViewController release];
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(pressButton1:)];
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
//Add buttons to the array
NSArray *items = [NSArray arrayWithObjects: systemItem1, flexItem,nil];
//release buttons
[systemItem1 release];
[flexItem release];
//add array of buttons to toolbar
[navController.toolbar setItems:items animated:NO];
//set navController's view in window hierarchy
[[self window] setRootViewController:navController];
[navController release];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
thx in advance!
The toolbar us hidden by default. The toolbarItems should be stored in the respective view controller, not the navigation controller.
From the documentation:
Displaying a Toolbar
In iOS 3.0 and later, navigation controller objects make it easy to provide a custom toolbar for each screen of a
navigation interface. The navigation controller object now manages an
optional toolbar in its view hierarchy. When displayed, this toolbar
obtains its current set of items from the toolbarItems property of the
active view controller. When the active view controller changes, the
navigation controller updates the toolbar items to match the new view
controller, animating the new items into position when appropriate.
The navigation toolbar is hidden by default but you can show it for
your navigation interface by calling the setToolbarHidden:animated:
method of your navigation controller object. If not all of your view
controllers support toolbar items, your delegate object can call this
method to toggle the visibility of the toolbar during subsequent push
and pop operations.
you can keep the toolbaritems like this
ThemeDetailViewController *themeDetail = [[ThemeDetailViewController alloc] init];
[self.navigationController pushViewController:themeDetail animated:YES];
themeDetail.toolbarItems = self.parentViewController.toolbarItems;

Adding items to a navigation toolbar

I have a navigation toolbar in which I am adding toolbar items programatically, as below. The toolbar displays properly, and the toolbar style is set to black opaque. but the button on the toolbar does not display. Why?
//Set up the toolbar
[[[self navigationController] toolbar] setBarStyle:UIBarStyleBlackOpaque];
UIBarButtonItem *myButtonItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(handleMyButton)];
NSArray *myItems = [NSArray arrayWithObjects: myButtonItem,nil];
[[self navigationController] setToolbarItems:myItems animated:NO];
[myButtonItem release];
UINavigationController fetches the buttons that should be used for the navigation bar and the tool bar from the current visible view controller. This means that you add the buttons you want to have to the view controller, not the navigation controller. So it should work just fine if you do:
[self setToolbarItems:myItems animated:NO];
Compare that with how the add button is added to the navigation bar in the default template for a Navigation Based Application with Core Data:
self.navigationItem.rightBarButtonItem = addButton;
This means that when you push a new view controller the buttons in the tool bar will disappear and then appear again when you pop back.
You are referencing the toolbar owned by your navigationController in the first line and not in the 4th line. It would appear that the necessary fix is:
[[[self navigationController] toolbar] setToolbarItems:myItems animated:NO];
instead of your current line 4.
Show the toolbar by setting the toolbarHidden property of the navigation controller object to NO.
To assign buttons to the toolbar you would call this method
[toolbar setItems:];
Instead of
[[self navigationController] setToolbarItems: animated:];

Back button on UINavigationController

I know that it could seem strange but i need to add a back button on the navigation Bar of the first navigationController's view. I tried like this:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Foo" style:UIBarButtonItemStyleBordered target:self action:#selector(foo:)];
self.navigationItem.backBarButtonItem=backButton;
if instead of backBarButtonItem i write leftBarButtonItem the button is showed. My problem is that i need an arrow button as the normal back button. Is this possible?
Usually this works out of the box, but sometimes with modal views / action sheets you may need this. Just before you instantiate your viewcontroller and push it onto navigationcontroller stack, try
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Back" style: UIBarButtonItemStyleBordered target: nil action: nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
[newBackButton release];
DetailViewController *detailVC = [[DetailViewController alloc]init];
[self.navigationController pushViewController:detailVC animated:YES];
[detailVC release];
I don't think you can do that on the first NavigationController view, because you need to set the backBarButtonItem property in the parent controller, before the child controller is pushed. Also, according the to the Apple docs, the target & action of the backBarButtonItem must be nil.
This question about creating a left-arrow button on a UIToolbar may give you some ideas of how you could work around this using a custom image (for the leftBarButtonItem).
or you could also do the following - I prefer this method. I got this from a different post.
Use following psd that I derived from http://www.teehanlax.com/blog/?p=447
http://www.chrisandtennille.com/pictures/backbutton.psd
Then I just create a custom UIView that I use in the customView property of the toolbar item.
Works well for me.
Hope that helps a little
Of course you can do this. You just need to change the leftBarButtonItem's title to back
then you will get a nice left arrow button with the title back. Then you just change the selector to actually perform a method when the button is clicked. So #selector(foo:)
Here some code on how to achieve the above:
self.navigationItem.leftBarButtonItem.style = UIBarButtonItemStyleDone;
self.navigationItem.leftBarButtonItem.title = #"Back";
self.navigationItem.leftBarButtonItem.target = self;
self.navigationItem.leftBarButtonItem.action = #selector(endTextEnteringButtonAction:);
Let me know if that helps.
Apple Document says:
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.
So If your navigation item is the top of the Stack (as we are talking here) you can't add the back button to the navigation controller, simply because no place he can navigate back to it because it's the top item in the stack.
Updated Answer :
After I searched I found work a round to make a back button in your root view controller in Navigation controller in these link
It's very simple :)
[self.navigationItem setHidesBackButton:YES animated:YES];
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Start" style:UIBarButtonItemStyleBordered target:self action:#selector(initializeStuff)];
self.navigationItem.leftBarButtonItem = backButton;

Add Custom buttons to Navigation Controller

I'm trying to either add 3 custom buttons to my navigation controller toolbar on the top of my view or add a segmented control with 3 options. I have the following code on my app delegate for when i create my view controller(fwc) but the buttons dont appear.
/*
Set up the navigation controller for the Feeding Tab
*/
// instantiate the feedingViewController and set the title to Feedings
feedingViewController *fwc =
[[feedingViewController alloc] initWithNibName:#"feedingViewController"
bundle:[NSBundle mainBundle]];
//fwc.title = #"Feedings";
// set the tab bar item up and add it as feedingViewController's tab bar item
UITabBarItem *feedingTabBarItem =
[[UITabBarItem alloc] initWithTitle:#"Feedings" image:nil tag:0];
fwc.tabBarItem = feedingTabBarItem;
[feedingTabBarItem release];
// create a new nav controller for feedings and add root view
feedingNavController = [[UINavigationController alloc] init];
//Create the add button, need to change the selector to something though *****
UIBarButtonItem *add = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(newFeeding)];
//self.navigationItem.rightBarButtonItem = add;
UIBarButtonItem *flexibleSpaceButtonItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil];
// Create and configure the segmented control
UISegmentedControl *sortToggle = [[UISegmentedControl alloc]
initWithItems:[NSArray arrayWithObjects:#"Ascending",#"Descending", nil]];
sortToggle.segmentedControlStyle = UISegmentedControlStyleBar;
sortToggle.selectedSegmentIndex = 0;
[sortToggle addTarget:self action:#selector(toggleSorting:)forControlEvents:UIControlEventValueChanged];
// Create the bar button item for the segmented control
UIBarButtonItem *sortToggleButtonItem = [[UIBarButtonItem alloc]initWithCustomView:sortToggle];
[sortToggle release];
// Set our toolbar items
feedingNavController.toolbarItems = [NSArray arrayWithObjects:
flexibleSpaceButtonItem,
sortToggleButtonItem,
flexibleSpaceButtonItem,
add,
nil];
feedingNavController.navigationController.navigationBarHidden=NO;
[sortToggleButtonItem release];
[add release];
// Push the feedingViewController on the nav stack and release it.
[feedingNavController pushViewController:fwc animated:NO];
[fwc release];
In order to use a UITabBar you would need a UITabBarController, which is different than the UINavigationController. A UITabBar has a fundamentally different use than a UISegmentedControl. It appears that the functionality you're trying to implement is not appropriate for a UITabBar. In your question description you mention trying to add these buttons to the "navigation controller toolbar on the top." A UINavigationController has a UINavigationBar, which is the bar that runs across the top, and a UIToolbar, which is the bar that appears at the bottom. The UIToolbar, by default, is set to hidden, but you get a UIToolbar for free whenever you create a UINavigationController (see the UINavigationController reference in Xcode).
Apple's NavBar demo shows how to put a UISegmentedControl into the UINavigationBar. Instead of a title, use a custom titleView to display the segmented control:
fwc.navigationItem.titleView = sortToggle;
If you want to put your add UIBarButtonItem in the UINavigationBar as well, you can use:
fwc.navigationItem.rightBarButtonItem = add;
Note that you shouldn't actually go about trying to customize the UINavigationController's navigation bar on your own. The proper way to customize is to have an individual view controller access it's own navigationItem and set the titleView and rightBarButtonItem with the items you want.
If you wish to approach your problem using a UIToolBar instead, meaning that your items will appear on the bottom of the screen, you can do something like this:
// Assume UIBarButtonItem *add, UIBarButtonItem *sortToggleButtonItem,
// and UIBarButtonItem *flexibleSpaceButtonItem are allocated
[fwc setToolbarItems:[NSArray arrayWithObjects:
flexibleSpaceButtonItem,
sortToggleButtonItem,
flexibleSpaceButtonItem,
add,
nil]];
[feedingNavController setToolbarHidden:NO];