"Back" button doesn't show up in UINavigationController - iphone

I'm using the following code to try to make a "back" button for my app, the view that this code is located is in a modal view (if that has any bearing?):
navBar = [[UINavigationController alloc] initWithRootViewController:tvController];
[navBar.view setFrame:CGRectMake(0, 0, 320, 460)];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: #"Back"
style: self.navigationController.navigationItem.leftBarButtonItem.style
target: self
action: #selector(backAction)];
navBar.navigationItem.backBarButtonItem.enabled = YES;
[self.view addSubview:navBar.view];
The view does not show at all, thank you for any tips!
EDIT: Even if I use a leftBarButtonItem, it still does not show up, I think there is some problem with the self.navigationItem bit of my code?

You need to make sure that when you present the modal view that you wrap it in a UINavigationController, then you'll have a valid navigation bar to manipulate. Otherwise you'll change the navigationItem all you want but it won't show up because you're not in a navigationController.
So when you go to present the view controller you're probably doing something like this.
SomeViewController *someViewController = [[[SomeViewController alloc] init] autorelease];
[self presentModalViewController:someViewController animated:YES];
What you want to do is present it like this
SomeViewController *someViewController = [[[SomeViewController alloc] init] autorelease];
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:someViewController] autorelease]
[self presentModalViewController:navigationController animated:YES];
Then when you're in the modal view you'll have a valid navigation bar that you can manipulate. Altering the leftBarButtonItem at that point will actually do something and be visible.
If you're trying to make this show a back button though you're probably "doing it wrong" typically if you're presenting something modally like this you'd show a "done" button. However by wrapping this with a navigation controller like this it does allow the modal view to then push and pop view controllers and operate as a normal navigation stack. But the root of it should probably have a "done" button not a back to return back to its previous state.

The backBarButtonItem property needs to be defined on the previous item in your stack, i.e. on the view controller you are going back to, not the current one.
EDIT:
OK, I see now you are adding your own custom navigation bar. In that case, you cannot use the view controller's navigation item. You must instead push your own navigation items on to the navigation bar and access those instead. For example:
UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:#"Back"];
item.leftBarButtonItem = ...;
[navBar pushNavigationItem:item animated:NO];

Related

Modal View with Navigation Controller's Bar

When I try to present a modalViewController, it covers up my navigation controller's navigation bar. Any tips? Thanks.
UPDATE (with code):
ComposeText *compText = [[ComposeText alloc] initWithNibName:#"ComposeText" bundle:[NSBundle mainBundle]];
compNavController = [[UINavigationController alloc] initWithRootViewController:compText];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:compNavController action:#selector(compDoneTapped:)];
compNavController.navigationItem.rightBarButtonItem = doneButton;
[self presentModalViewController:compNavController animated:YES];
compText.title = #"Compose";
[doneButton release];
Everything seems to be in order, but the button is still not appearing on the navigation bar.
That's what it is supposed to do. If you want a navigation bar, present a new UINavigationController modally and set it's root view controller to your modalViewController.
The question you need to ask yourself is: "why do I want to show my navigationbar". If it is to give the user access to some buttons then it is the wrong reason. Modal view controllers are there to take full control of the screen and to not allow the user to manipulate anything else in the app until the controller is dismissed. If you don't want that do as Cyprian suggests and push a viewcontroller on your navigation stack.
If it is just a visual thing (logo ...) duplicate it in your modal view controller.
UINavigationController has it's own method to show another viewController.
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
It uses stack, to push new viewController so it can handle its navigation with buttons.

Maintain Title Bar in ModalViewController

When using the modalViewController, I found that that only way to keep a title bar and buttons on the screen that I jump to was to create a navigation controller and set the modalView screen as the rootView of the navigation controller (as below).
userNameViewController = [[UserNameViewController alloc] init];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:userNameViewController];
[self.navigationController presentModalViewController:cntrol animated:YES];
[userNameViewController release];
[cntrol release];
Why can't I simply this by using the original viewController as the modalView (as below)?
userNameViewController = [[UserNameViewController alloc] init];
[self presentModalViewController:userNameViewController animated:YES];
Because the navigation bar you usually see belongs to the navigation controller, not to its children view controllers.
You could create your own navigation bar and add it to your controller's view. However, it would require some relayout (and that's probably why it's easier to just recreate a navigation controller).

Custom UITabBarController

I want to customize the look and feel of the tab bar of a UITabBarController. I want to change the colors, the way the icon looks when they are selected, and also, most important of all, I want to reduce the size of the custom toolbar.
My approaches for this and the hurdles in it are:
A) The first solution which came to my mind was to create my own viewController which will act like a UITabBarController with buttons in the bottom and add this viewController to the window. Once when user taps a button at the bottom, swap the view in the viewable area with the new viewController's which corresponds to the button now tapped by user.
The problem with this strategy is: since I swap view's the corresponding viewControllers will not get these messages:
viewWillAppear
viewWillDisappear
viewDidAppear
viewDidDisappear
And all the rotation events
B) I could have used the accepted answer's approach in this thread:
Custom UITabBarController Problems with View Controllers and Views
But my tabBar's height is not the same as the default.
Due to the cited reasons above, I cannot use those approaches.
Having said this, I have no special requirement of More tab. I will be having only 5 tabs which will be displayed by the tab bar and hence the re-ordering of tab bar items is out of scope.
Awaiting suggestions and ideas.
I have never attempted something like this but as I see it, you are supposed to send those messages to your child view controllers manually.
It shouldn't be problem to send -viewWill/Did(Dis)Appear to the right controller at the appropriate moment. This is what UITabBarController does, too.
As for rotation events:
In shouldAutorotateToInterfaceOrientation:, forward this message to your child controllers and set your return value depending on their return values (UITabBarController only returns YES if all its child controllers return YES for the requested orientation).
Forward willRotateToInterfaceOrientation:duration:, didRotateFromInterfaceOrientation: and willAnimateRotationToInterfaceOrientation:duration: to the child controllers (at least to the currently visible one) when you receive them.
If you have set the autoresizing masks of your child controllers' views correctly, they you rotate and resize correctly when the system rotates your custom tab bar controller's view. (At least I think that's how it should work.)
Again, I'm not sure if this will work.
You can implement the following code for the creating the custom tab bar in that use to images using the CGRect make.further code is use for the creating the custom tab bar
-(void)applicationDidFinishLaunching:(UIApplication *)application {
// Add the tab bar controller's current view as a subview of the window
tabBarController.delegate = self;
tabBarController = [[UITabBarController alloc] init];
mainDashBoard = [[DashBoard alloc] initWithNibName:#"DashBoard" bundle:nil];
mainSearchView = [[SearchView alloc] initWithNibName:#"SearchView" bundle:nil];
mainMoreView = [[MoreView alloc] initWithNibName:#"MoreView" bundle:nil];
UINavigationController *nvCtr0 = [[[UINavigationController alloc] init] autorelease];
UINavigationController *nvCtr1 = [[[UINavigationController alloc] initWithRootViewController:mainDashBoard] autorelease];
UINavigationController *nvCtr2 = [[[UINavigationController alloc] initWithRootViewController:mainSearchView] autorelease];
UINavigationController *nvCtr3 = [[[UINavigationController alloc] initWithRootViewController:mainMoreView] autorelease];
UINavigationController *nvCtr4 = [[[UINavigationController alloc] init] autorelease];//[[[UINavigationController alloc] initWithRootViewController:nil] autorelease];
tabBarController.viewControllers = [NSArray arrayWithObjects:nvCtr0,nvCtr1,nvCtr2,nvCtr3,nvCtr4,nil];
nvCtr0.tabBarItem.enabled = NO;
nvCtr4.tabBarItem.enabled = NO;
[window tabBarController.view];
}

Three20 TTLauncher Issues

So, I'm having some issues with my implementation of the Three20 TTLauncherView. I am using their code, not a fork (although I have heard of rodmaz's version), and I can't get it to work properly. This is what my app looks like.
alt text http://img709.imageshack.us/img709/8792/screenshot20100715at409.png
I removed the icon image, that's not the issue. The issue is, at the top there is no Navigation bar at all, and I believe also causes the white strip at the bottom, which appears to have the same dimensions as a Nav Bar. I've spent quite a while looking through their code and can't figure this out at all. It looks like their Navigation bar (as seen in their Catalog example app) stems from the TTTableViewController, or something further up. However, my app starts like the Facebook app does, not into a table, but into the TTLauncherView. So... how do I get the Navigation bar into my TTLauncher view, if it goes "App Delegate -> TTLauncherView Subclass"
Thanks for your help!
Edit:
Added the code I used. I put this in my app delegate, wrapping my first view with the UINavigation Controller, and it worked just as I wanted!
MainViewController *aController = [[MainViewController alloc] initWithNibName:nil bundle:nil]; //my Main view
self.mainViewController = aController;
[aController release]; //release for Memory Management
self.mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
UINavigationController *navigationController = [[UINavigationController alloc] init];
[navigationController pushViewController:self.mainViewController animated:NO]; //Gets the main view on the screen
[window addSubview:navigationController.view];
You simply wrap the view with a navigation bar before you push the new view. As an example, here is a snippet of my code where I present a modal view controller with a navigation bar.
- (IBAction) showNewNavView: (id) sender
{
// Present it as a modal view and wrap the controller in a navigation controller to provide a navigation bar for the Edit and Save buttons
ModalViewController *addController = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
addController.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addController];
navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[addController release];
}
If you want to add any buttons or set the title of it, you need to do that in the viewDidLoad method of the view that you are pushing (i.e. your TTLauncher view)

Back button of Navigation Controller does not work!

For some reason, if I try to go back to the main menu using the back button on the upper left corner, only the title returns to the previous menu, but not the view controller. View controller would return to the previous menu only if I explicitly call popViewControllerAnimated using some other button.
Is there anyway to solve this? I think I've coded something wrong. Tried googling but couldn't find any cases like mine.
I'm getting the exact same problem. Here is my code:
- (IBAction) showGameView:(id) sender {
gameView = [[TCGameViewController alloc] initWithNibName:#"TCGameViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:gameView animated:YES];
[gameView release];
}
And when I am done with gameView, I do this:
[self.navigationController setNavigationBarHidden:NO animated:YES];
But all it does when I push the 'back' button is cycle through the navigation bar, but never pops the view. I don't even know how to debug it.
In my other view, "infoView" I call the same code as before except the NavBar is never hidden, but it works just fine.
helps!
This problem can occur when you override the following method in your custom view controller:
- (UINavigationItem*)navigationItem
But you don't specify a UIBarButtonItem for the leftBarButtonItem property of the returned UINavigationItem.
If you use a custom navigationItem, and want the standard back button functionality, you could add a method as follows (remember that every UIViewController has a reference to the navigationController that containts it):
- (void)backButtonTapped
{
[self.navigationController popViewControllerAnimated:YES];
}
And then setup part of the custom navigationItem as follows:
- (UINavigationItem*)navigationItem
{
UIBarButtonItem* newLeftBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(backButtonTapped)];
UINavigationItem* navigationItem = [[[UINavigationItem alloc] init] autorelease];
Hope this helps.