UINavigationController and modalViewController problems - iphone

Hi I'm having this problem:
I have a UITabBarController with UINavigationControllers in each tab.
However, I'm trying to implement an action that, when I click on a button, should present me a new view with a UINavigationController (since it will be multi-view) in a modal way.
What I've tried is to implement a new UIViewController, with a NavigationBar. And then on the button handler I wrote something like this:
SendMessageViewController *v = [[SendMessageViewController alloc] initWithNibName:#"SendMessageView" bundle:nil];
UINavigationController *t = [[UINavigationController alloc] initWithRootViewController:v];
[(UINavigationController *)[tabbar.viewControllers objectAtIndex:0] presentModalViewController:t animated:true]; // hardcoding 0, I know
However, the modal view that's pushed appears with 2 navigation bars, one empty, and my other defined on the "SendMessageView" XIB.
Is there a way to solve this? I don't want to create a XIB just to contain a UINavigationController.. I thought I could do it programatically.

What you want to do is this:
[tabBarController presentModalViewController:t animated:Y];
Basically, get a handle to the tab bar ViewController, and then you'll have the single nav bar you were seeking.

Related

Modal ViewController has white stripe on bottom

I have a ViewController subclass that I'm presenting as a modal view:
MyViewController *myViewController = [[MyViewController alloc] init];
[self presentModalViewController:myViewController animated:YES];
However, the modal view showing up with a white stripe on the bottom, approximately the height of the title or navigation bar. My app is otherwise navigation controlled. How do I get rid of the white stripe (and ideally add a title bar)?
I'm not sure if this is one of two things from your question, are you trying to add a navigation controller to your modal view controller, or are you trying to hide your navigation controller from your modal view.
I suspect you may want to in fact change your code to the following to present your modal view controller from your NavigationController
MyViewController *myViewController = [[MyViewController alloc] init];
[[self navigationController] presentModalViewController:myViewController animated:YES];
Then call setTitle: on you MyViewController object to set the title for it.

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.

UITabBar Modal ViewContoller

I'm trying to present a TabBarController on top of another TabBarController. My application's MainWindow.xib looks like this:
Files Owner
First Responder
My App App Delegate
Window
TabBarContoller
+TabBar
+Nav Controller Subclass (a custom class)
+Navigation Bar
+Table View Contoller Subclass (custom class)
+Tab Bar Item
+Second View Controller (not yet hooked up)
I'm trying to display a xib file when an item is clicked in the TableView. This xib file has a TabBarController as it's main view, but when the view displays, the tab bar and navigation bar are both invisible. The code I'm using to display it is:
MyAppAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.customNavController presentModalViewController:customDetailEditViewController animated:YES];
If I use the code below to push the view controller onto the stack, I see the correct navigation bar, but the TabBar from the root view controller is shown instead of the one from the view which has been pushed.
[delegate.customNavController pushViewController:customDetailEditViewController animated:YES];
I even tried removing the TabBarController and manually implementing my own TabBar delegates but the same effect occurs (either no NavigationBar or TabBar, or the NavigationBar/TabBar from the root ViewController).
EDIT: I've uploaded the source to http://mi6.nu/tabcontroller.zip . I'd really appreciate it if someone with a bt more experience with iOS could take a look.
EDIT2: The closest I've come so far is presenting a modal view controller inside the first tabbar, so my view looks like this:
NavigationBar
[ ]
[ ]
[---View---]
[ ]
[ ]
TabBar from the pushed view
TabBar from the root view
To achieve this, I'm using:
UITabBarController *tabBarController = [[UITabBarController alloc] init];
UIViewController *directionsView = [[UIViewController alloc] init];
txtDirections = [[UITextView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height)];
[directionsView.view addSubview:txtDirections];
IconPickerViewController *iconPicker = [[IconPickerViewController alloc]init];
tabBarController.viewControllers = [NSArray arrayWithObjects:recipeDetailEditViewController,directionsView,iconPicker, nil];
[directionsView release];
[iconPicker release];
MyAppAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.rootNavController presentModalViewController:recipeDetailEditViewController animated:YES];
This just complicates everything though, since a) It's not ideal as I have two tabbars and b) all controls (all of the editing controls) need to be in the TableViewController so their values can be loaded/saved to edit items. It would be much easier if the pushed view could handle loading/saving and appear on top of the root tabs.
Surely this must be possible?
This was an absolute nightmare, but I eventually got it working by presenting the view modally from the TableViewController when the add button is clicked:
[delegate.rootController presentModalViewController:recipeDetailEditViewController animated:YES];
delegate.rootController is the root TabBarController
The XIB file I'm presenting does not have a TabBarController, but rather a UIView, a Navigation bar and a TabBar. This appears to work when presented modally from inside a NavigationController.
Why are you putting everything in your main.xib?
Try moving the second tab bar out of the main window xib and instead put it inside the customDetailEditViewController.

Pop-up modal with UITableView on iPhone (follow)

I've read the post : Pop-up modal with UITableView on iPhone
and I don't understand the following part of the answer (as I can't comment the original post, I create this new question) :
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:optionViewController];
Why allocate a new controller as the window from where the new optionController is called may already have one ?
What if I just write :
OptionViewController* optionViewController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:nil];
[self.navigationController presentModalViewController:optionViewController animated:YES];
It seems to work...
If I have a list, that goes to a detail View, from where I switch to a modify view, and then from where I call this option window, what would be the code to use to call this optionWindow ? This one ? Any other one ? I really have a problem dealing with UINavigationController between screens... (where should be defined the first one, what should be passed between screens, when may I create a new one, ...)
Modal views don't use the UINavigationController of their parent. This means that if you need a "stack" of new view controllers in your modal view then you'll need to add your own. On the other hand, if you don't need the functionality of a navigation controller in your modal view then there's no reason to add one.
Here are sone more details of how I did it in two of my apps:
My root view controller has a UINavigationController. I open a modal view using this code:
TwitterPostViewController* vc = [[TwitterPostViewController alloc] init];
[viewc presentModalViewController:vc animated:YES];
[vc release];
The modal view is then dismissed using this code:
[self dismissModalViewControllerAnimated:YES];

How to hide a tabbar at the app startup?

So, I want my app starts with a UIViewController(without seeing a tabbar), and then enter a UITableView with navigationbar and tabbar. the problem is that the Tabbar is visible at the app starts up, anyone can help on this will be very appreciated...
I think you should either send -presentModalViewController:animated: to your main UIViewController with the tab bar controller as an argument or just do this:
[myWindow addSubview: myTabBarController.view];
Make your app a navigation based application (rather than a tab bar based one) then add a tab bar on the UITableView.
There is help for adding the UITabBar here
I do it like this : in this case drawing a table view and map view (From the Locati application)
tabBarController = [[UITabBarController alloc] init]; // creates your tab bar so you can add everything else to it
searchTableViewController = [[SearchTableViewController alloc] init]; // creates your table view - this should be a UIViewController with a table view in it, or UITableViewController
UINavigationController *searchTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchTableViewController] autorelease];
[searchTableViewController release]; // creates your table view's navigation controller, then adds the view controller you made. Note I then let go of the view controller as the navigation controller now holds onto it
searchMapViewController = [[SearchMapViewController alloc] init];
UINavigationController *mapTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchMapViewController] autorelease];
[searchMapViewController release]; // does exactly the same as the first round, but for your second tab at the bottom of the bar.
tabBarController.viewControllers = [NSArray arrayWithObjects:searchTableNavController, mapTableNavController, nil]; //add both of your navigation controllers to the tab bar. You can put as many controllers on as you like
I found this pattern a long time ago. Sorry that I can't point at the original.
YOu then need to add the tabbarcontoller to the relevant view ([...view addSubView:tabBarController];) possibly setting frame first.