Customizing UIBarButtonItem - iphone

I have a custom button I want to add onto the navigation bar. So here's what I have so far in my RootViewController (which inherits UIViewController, the UINavigationController is added through the AppDelegate):
In viewDidLoad:
UIBarButtonItem *share = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"icon"] style:UIBarButtonItemStylePlain target:self action:#selector(share:)];
self.navigationController.navigationItem.rightBarButtonItem = share;
Here's how my UINavigationController is set up:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *rootViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbar"] forBarMetrics:UIBarMetricsDefault];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Why is this not working?
EDIT:
It worked after I replaced self.navigationController.navigationItem.rightBarButtonItem with self.navigationItem.rightBarButtonItem. Why is that? My rootviewcontroller is of type UIViewController and I should access navigationItems through navigationController. What is navigationController in this case?

It worked after I replaced self.navigationController.navigationItem.rightBarButtonItem with self.navigationItem.rightBarButtonItem. Why is that?
Every instance of a UIViewController has a navigationItem. This includes UINavigationController, which is a subclass of UIViewController.
navigationItem is used by a UINavigationController to update its visual state when a new view controller appears. When you modify self.navigationController.navigationItem, you are modifying what would be displayed if you had nested UINavigationControllers. In practice, you will never modify the navigationItem of a UINavigationController because you will not have nested navigation controllers.
As you've discovered, you must modify the view controller's navigationItem in order for the changes to take affect in the navigation controller.
What is navigationController in this case?
navigationController is a reference to the UINavigationController that the view controller represented by self is currently contained within.
For example:
UIViewController* viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:viewController];
// This is TRUE: viewController.navigationController == navController

Based on Apple UINavigationController reference by Updating the Navigation Bar, it is stated that
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 new top-level view controller has a custom right bar button
item, that item is displayed. To specify a custom right bar button
item, set the rightBarButtonItem property of the view controller’s
navigation item.

Related

Navigation controller with 3 tabs inside and no working title

I have 3 tabs and main navigation controller. I implements with code:
UIViewController *monitorController = [[[MonitorController alloc] initWithNibName:#"MonitorController" bundle:nil] autorelease];
UIViewController *dashboardController = [[[DashboardController alloc] initWithNibName:#"DashboardController" bundle:nil] autorelease];
UIViewController *settingsController = [[[SettingsController alloc] initWithNibName:#"SettingsController" bundle:nil] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:monitorController, dashboardController, settingsController, nil];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:self.tabBarController] autorelease];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
I want to change navigation title when I select another tap, but no variant (see below) not working (there are no any title at navigation controller):
self.title = DASHBOARD_TITLE;
self.navigationController.title = DASHBOARD_TITLE;
How I can resolve this problem?
The UINavigationController will display the title of the UIViewController it's currently displaying, that is why you are not able to set it directly.
You may try to change the title on your UITabBarController, but I'm not sure the navigation controller will update it's title after it first appeared on screen.
But, Do you really need that Architecture?
Usually the UITabBarController is the root viewController and if you need UINavigationControllers they are place inside the Tab that need to have navigation capability.
It was design to be use that way.
Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
Quoted from UITabBarController Class Reference
Sorry I misread your question, what you have to do is to implement -tabBar:didSelectItem: from UITabBarDelegate protocol, and then change the title according to the pressed tab.
Or in the ViewWillAppear method of your controllers set the title, the way you were doing it

Navigation-based app with TabBar

I'm using Navigation-based Application Template with Core Data. Could anyone please tell me how to and a TabBar on the bottom of the view. I am using UITableView, so If I add UITabBar as subview, the TabBar is moving along with tableView when scrolling. I would like to switch between views with TabBar, first "segment" of TabBar should open the RootView (NavigationBar with TableView),and second some other view.
Now I did this:
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewController = [NSArray arrayWithObject:yourNavigationController];
self.window.rootViewController = tabBarController
[tabBarController release];
that works fine, but how can I add more Items to UITabBar and for each Item some other view? TabBar has now just one Item on which rootView is loaded
Thanks!
Use UITabBarController as your root view controller in your application delegate:
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewController = [NSArray arrayWithObject:yourNavigationController];
self.window.rootViewController = tabBarController
[tabBarController release];
Its simple one, just add UITabbarController to your code and then made the first tab controller to be a navigation controller. And point that navigation controller to your controller which has table view that you want to show.
If you are doing it programmatically you can use this:
FirstViewController *first=[FirstViewController alloc]]init];
UINavigationController *nav=[UINavigationController alloc]]initwithRootViewcontroller:first];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewController = [NSArray arrayWithObject:first];
[tabBarController release];

Combining UITabController & UINavigation controller programmatically http://t.co/R52RlUL UITabController & UINavigation controller programmatically

I have created a UItabbarcontroller and 2 views with UITableViews just using code (no IB stuff) and I want to now add a navigation bar at the top that will include add and edit buttons, however I seem to be tripping up and blowing my app up or adding navgation controller to a 3rd tab only.
Here is my main code for adding the tab bar and switching views
FYI - I am using XCode4
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.mainTabBar = [[UITabBarController alloc] init];
// create the 2 views
tableViewController* vc1 = [[tableViewController alloc] init];
tableViewController2* vc2 = [[tableViewController2 alloc] init];
// put them in an array
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, nil];
// for the tab bar
mainTabBar.viewControllers = controllers;
// Add the tab bar controller's current view as a subview of the window
[self.window addSubview:self.mainTabBar.view];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
Where do you want navigation controller(s)? You have to create one for each tab you want one in the UITabBarController.
You add a navigationController in conjunction with the first view controller on its stack. Try this:
// create the controllers for UITabBarController
tableViewController *vc1 = [[[TableViewController alloc] init] autorelease];
navController *nav1 = [[[UINavigationController alloc] initWithRootViewController:vc1] autorelease];
tableViewController *vc2 = [[[TableViewController alloc] init] autorelease];
navController *nav2 = [[[UINavigationController alloc] initWithRootViewController:vc2] autorelease];
// put them in an array
NSArray *controllers = [NSArray arrayWithObjects:nav1, nav2, nil];
// rest of your code
Also note that you need to release anything you alloc or retain. You can do it as I did by adding autorelease when you initialize them or you can release them explicitly after you've added them to the controllers array.
You then configure the navigationItem for each view controller in its loadView or viewDidLoad method depending on how you implemented it.

How do I display the UINavigationBar on a modally presented UITableViewController?

If you have a UINavigationController's UIViewController present a UITableViewController (TVC) modally, is there a way for the TVC to display the UINavigationBar of its parentViewController? Or, should I have it create a new UINavigationBar, item, buttons, etc. for the modal TVC?
I would just instantiate a UINavigationController right before you present your modal.
YourViewController *modalViewController = [[YourViewController alloc] initWithNibName:#"foo" bundle:nil]
UINavigationController *tmpNavController = [[UINavigationController alloc] initWithRootViewController:modalViewController];
[modalViewController release];
[self.navigationController presentModalViewController:tmpNavController animated:YES];
[tmpNavController release];
This is just back-of-the-envelope - I wouldn't copy and paste that code w/o a double-check!

Help with navigation Controller, windows & subviews!

my first xib contains a ScrollView with a springboard like interface in MainWindow.xib:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navController = [[UINavigationController alloc] init];
[navController setNavigationBarHidden:YES];
[window addSubview:navController.view];
[window sendSubviewToBack:navController.view]; }
When a button is clicked the FirstViewController appears with a tableview and a navigation controller:
- (void) buttonPushed:(id)sender {
FirstViewController *firstViewController = [[FirstViewController alloc] init];
[navController pushViewController:firstViewController animated:YES];
[firstViewController release];
[window addSubview:navController.view]; }
When I click the back button in Navigation Controller to go back to springboard, I get the springboard xib, but unresponsive to touches with a Navigation Bar on top!
- (void)goHome:(id) sender {
[self.view removeFromSuperview];
How can I go back to springboard screen (mainwindow.xib) without having the navigation bar stacked on top, and be responsive to touches ?
Why don't you set the springboard view to be the root view controller of your navigation controller and get rid of any UI in the window?
I think that the window shouldn't have any UI elements accept view of view controllers that are added to it (by navigation controller or by tab bar controller).
This way you won't have to reinvent the wheel for the first view to load from the springboard view and the back button will work properly.
You can set the navigationBarHidden property to false in the viewDidLoad method of the root view controller (the view controller of the springboard view).
Did you try calling [navController setNavigationBarHidden:YES]; in your mainview viewWillAppear callback ?
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
UIViewController *rootController = [[MyRootViewController alloc] init];
navigationController = [[UINavigationController alloc]
initWithRootViewController:rootController];
[rootController release];
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
}