UITabBar Modal ViewContoller - iphone

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.

Related

Custom TabBar navigation issues

I implemented a custom tab bar controller as a set of buttons each one related to it's own View Controller. I guided on this link http://idevrecipes.com/2011/01/04/how-does-the-twitter-iphone-app-implement-a-custom-tab-bar/ to achieve the behavior. So the relevant part of code is as follows:
- (void) selectedItemAtIndex:(NSUInteger)itemIndex
{
// Get the right view controller
NSDictionary* data = [self.tabBarItems objectAtIndex:itemIndex];
UIViewController* viewController = [data objectForKey:#"viewController"];
// Remove the current view controller's view
UIView* currentView = [self.view viewWithTag:SELECTED_VIEW_CONTROLLER_TAG];
[currentView removeFromSuperview];
// Set the view controller's frame to account for the tab bar (+ 48)
viewController.view.frame = CGRectMake(0,48,self.view.bounds.size.width, self.view.bounds.size.height - 48);
// Se the tag so we can find it later
viewController.view.tag = SELECTED_VIEW_CONTROLLER_TAG;
// Add the new view controller's view
[self.view insertSubview:viewController.view belowSubview:self.tabBar];
//Keep track of current view controller
self.currentController = viewController;
}
So far is working, I can see each view controller in a similar maner to the default TabBarViewController. But then there's a requirement where I need to push a new navigation controller modally (it should take all the application frame) from inside one of the tabBar controllers.
At first glance I tried the following code from within one of the tab controllers:
DetailViewController *detailViewController = [[DetailViewController alloc]init];
UINavigationController *navigationController = [[UINavigationController alloc]detailViewController];
[self presentModalViewController:navigationController animated:YES];
However is not working as expected, first the view is shown below the TabBar and second the new view is not taking in consideration the parent view frame which should be the screen bounds less the tabbar. (0, 48, 360, 412). My detail view controller it's loading content from a nib file.
Well, this is quite obvious since the TabBar Controller is inserting each view below my custom TabBar.
[self presentModalViewController:navigationController animated:YES];
So I tried inserting it directly as a window subview:
[[UIApplication sharedApplication].keyWindow addSubview:navigationController.view];
But, I think this is not okay... there should be a better approach that I can't figure out. So if anybody could give me suggestions on how to correct or improve this navigation system it would be great.
Thanks a lot.
If you are building you app for iOS 5.0 and up you can make use of childViewController. In your custom Tab Bar you can have a containerView and a tabView.
The view of viewController is added to containerView. All the necessary events are generated to the subsequently added viewController if the following methods are implemented correctly
- (void)addChildViewController:(UIViewController *)childController;
- (void)removeFromParentViewController;
More about viewController containment can be found here.

UINavigationController navigationbar visibility set not works

I'm trying to add some navigation controller in my app, it's sth likes:
in my index page view controller, I try to initialize the navigation controller like this:
-(void)viewDidLoad{
...
//allocate a navigation controller.
myNavigationController = [[UINavigationController alloc]init];
myNavigationController.delegate = self;
myNavigationController.navigationBar.hidden = YES;
[self.view addSubview:myNavigationController.view];
[myNavigationController pushViewController:tabViewController animated:YES];
[self presentModalViewController:myNavigationController animated:YES];
}
Here, index page view controller is the root view controller of my app, it's just a common UIViewController here.
[myNavigationController pushViewController:tabViewController animated:YES];
The tabViewController here I've pushed into the navigation controller is a custom tabview controller which makes use of a container view to hold the tab button and also holds an navigation controller for tab switching.
The problem here is:
myNavigationController.navigationBar.hidden = YES;
since I've make the navigation bar invisible, it doesn't show when my custom view controller shows, but when I'd like to switch to some other view controller with the navigation controller and I also want the navigation bar visible:
myNavigationController.navigationBar.hidden = NO;
MyViewController *toSwitchNC = [[MyViewController alloc]init];
[myNavigationController pushViewController:toSwitchNC animated:YES];
The navigation bar would never show any more. I've also tried to put:
self.navigationController.navigationBar.hidden = NO
in MyViewController's viewDidLoad, ViewDidAppear or even in the navigation controller's delegate method, it didn't show the navigation bar neither.
So what's wrong with it? Why I initialized the navigation bar to be invisible at first, it will never show again even I set the hidden flag to be false?
Okay, I've got this fixed by removing the navigation controller container in my index page view controller. This might be a stupid question, since apple've formally stated in the developer document that the navigation view controller should be place as root as possible in the view stack. Since IOS is a closed system, who knows WTH is going on under-beneath except Apple.

iPad App behavior: a navigationcontroller with a tabbarcontroller with more tabs

For the impatient:
I want to have a navigationcontroller who's root viewcontroller is a tabbarcontroller, similar to the iPad application. I am using IOS 5 and Storyboards.
For the reading inclined:
In my storyboard I have 6 tabs in a UITabBarController that is embeded in a UINavigationController, giving it a "More" button after 3 tabs are shown.
doing so gives me two navigation bars when more is pressed:
So I subclass TabBarController:
//#implentation MyTabController
- (void)viewDidLoad
{
self.moreNavigationController.wantsFullScreenLayout = NO;
self.delegate = self;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
// hide nav bar if current controller is "More" controller
self.navigationController.navigationBarHidden =
viewController == self.moreNavigationController;
}
Great, this gives me:
My guess was that i needed to relayout the views to account for the statusbar, so i try
[self.view setNeedsLayout:YES];
but i get an error saying UIView does not contain a selector for setNeedsLayout so...
How do I get the moreNavigationController.navigationBar to account for the statusbar?
Update:
I have a second related issue with this. When I hit the "Edit" button the edit controller shows modally. Its navigationbar displays underneath the insured controller (after an animation), and does not receive touches.
Pushing a tabBarController into a NavController isn't recommended, instead set a NavigatorController for every tabBar View controller, and set the TabBarController as the main window root view controller.
If you want to be able to show a screen before showing the tabbar, a solution is to push in all the navigator controllers the previous view controller, followed by the one you want to show (that way all navbars has the backbutton). Then set hidesBottomBarWhenPushed = YES to the first view controller, that way it won't show the tabBar.
Example Code:
UIViewController *prevc = [[UIViewController alloc] init];
//prevc.hidesBottomBarWhenPushed = YES;
//Do this for every VC that will be a tabBarItem
UIViewController *vc1 = [[UIViewController alloc] init];
UINavigationController *nv1 = [[UINavigationController alloc] initWithRootViewController:prevc];
[nv1 pushViewController:vc1 animated:NO];
//Remember to set the tabBarItem!
UITabBarController *tb = [[UITabBarController alloc] init];
tb.viewControllers = [NSArray arrayWithObjects:nv1, nv2, nv3, nil];
I just realized that setting hidesBottomBarWhenPushed to the previous ViewController won't work well, but If you show prevc first, and then push the following viewController, you won't have problems. But if anyway you wan't to hide the tab bar while doing a pop, please check this:
hidesBottomBarWhenPushed but when popped
I have also faced a similar problem. In my application also, there is a Tabarcontroller inside a Navigation controller. When i try to switch to a view controller in more navigation controller programatically (like : [self.tabBarController setSelectedIndex:X]; ) the same issues appears in my application. But the following code solves my problem.
self.tabBarController.moreNavigationController.navigationBarHidden = YES;

how to remove a navigation controller with a view

I have a tabbar application with a navigation bar. For one of the actions I am instantiating a navigation controller programatically and adding a view with tableview. I want to remove this navigation bar and tableview programatically clicking a button on the new navigation bar. how to do this ?
I tried popview but it is not poping out.
To hide it
[[self navigationController] setNavigationBarHidden:YES];
If you have added a UINavigationController on top of another UIViewController, then from the uiNaviagation controller, you will not be able to remove the navigation bar even if you remove the current view, and all the subview. (the parent uiviewcontroller also get the nav bar)
One way to fix this is, access the app delegate, and remove the top view from the window before
adding the UINavigationController
AppDelegate *dg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *ar = [[dg window] subviews];
//then remove all the views in ar
//then add uinavcontroller
[[dg window] addSubView:[uinavcontroller view]];
then add UINavigationController, when you want to replace the UInavigationcontroller with the first UiViewController. do the similar steps like above.

UINavigationController and modalViewController problems

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.