I have created an application that have 9 screen and I have added tabbar in it which contain 4 baritem.
Now I have two problems -
1 => My last baritem is logout button, I don't want to display view controller for it, simply when user click this button then alertview should pop up and ask for logout and if user says yes then it will logout.
2=> How to display tabbar in that view controller that does not added in tabbar, because I have 9 screen and only 4 screen display in tabbar.
UPDATE
I said that I have 9 view controller in my app
like...
firstViewController
secondViewController
thirdViewController
fourViewController
|
|
ninthViewController
But my tabbar have only four view controller in baritem which are -
firstViewController
secondViewController
thirdViewController
fourViewController
Now, my other view controller does not display tabbar.
I dont know this is right way or not but you can do it like this...
first read this question that show how to display login and come back to home.
Now add this code in didFinishLaunchingWithOptions method
UIViewController * logoutVC =[[UIViewController alloc] init];
NSArray *viewControllersArray = [[NSArray alloc] initWithObjects:firstView, secondView, thirdView,logoutVC, nil];
self.tabController = [[UITabBarController alloc] init];
[self.tabController setViewControllers:viewControllersArray animated:YES];
[self.window addSubview:self.tabController.view];
And implement this delegate method of tabbar
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//select the index where your logout button is
if ([tabBarController selectedIndex] == 3) {
NSLog(#"logout");
self.tabController.selectedViewController = fistView; //firstview is your home screen
//LOGOUT
LoginViewController * vc = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
vc.delegate = self;
[self.tabController presentModalViewController:vc animated:NO];
}
}
Your first question:
Don't do this, it's an abuse of tab bar controller. Each item on the tab bar controller should be a different view in your app, not an action. Find an appropriate place for a logout action button.
Your second question:
There are several ways to show a view controller that isn't one of the main VCs for the tab bar controller. It could be reached by:
being shown as a modal screen
as a popover
Update
To show a 'secondary' view controller that isn't a main VC of the tab bar, but still have the tab bar visible, you can present that secondary VC as a sub-viewcontroller of a main tab bar VC. In other words, present the view of your secondary VC as a subview of a main VC view.
Related
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;
I have a navigation view controller which navigates between some tableviews and I've just added an "edit" button inside the cells of one of the tables. What I'd like to happen is for the user to tap the edit button inside the cell and for the navigation controller to shunt across a new view where all of that cell's content is laid out for easy editing.
The cell, however, has no access to the navigation controller and cannot push a new view controller on to its stack. How can I do what I want?
Note that I am not using segues and storyboards as it's an old app and I want to continue supporting devices running iOS 4.
You should set the target of the button to the UIViewController that is already on the stack?
If you don't want to add this new view to the Navigation (Stack), Simply use the PresentModalViewController
// In action method for edit button
- (void)editButtonClicked {
EditViewController *editViewController = [[EditViewController alloc] initWithNibName:#"EditViewController" bundle:nil];
[self.navigationController presentModalViewController:editViewController animated:YES];
[editViewController release];
}
I'm not sure if you want this, but you can try:
// In action method for edit button
- (void)editButtonClicked {
EditViewController *editViewController = [[EditViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:editViewController animated:YES];
[editViewController release];
}
I Have a TabView control, and when the user clicks on the tab item, the view will load.
When the view is loaded, there is a button on the view, and when i click on the button, another view gets loaded, i used the following code to load the view:
NextView *next = [[NextView alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:next animated:NO];
But when the view loads, the tab bar items are not displayed. It loads on top of the tab bar items. how can i make the view pop out with the tab bar items ?
NextView *next = [[NextView alloc]initWithNibName:#"yourNibName" bundle:nil];
[self presentModalViewController:next animated:YES];
if you are using presentModalViewController then you can't display the tabBar instead you can use pushViewController
Im having a strange bug in my code while working on an app for iphone. I am creating a navigation controller and putting it within my tab bar controller and then when i move from my initial screen to a secondary screen the back button on the secondary screen points to itself. so when back is pressed it just reloads itself and then the next time it is pressed it goes back to the first screen.
UINavigationController *nav1 = [[UINavigationController alloc] init];
// create the initial views for each nav controller
SearchViewController *searchView = [[SearchViewController alloc] init];
searchView.title = #"Search";
//place all the viewcontrollers on the nav controllers ready to view
[nav1 pushViewController: searchView animated:NO];
//create tab bar out of above nav controllers
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"Search" image:[UIImage imageNamed:#"search.png"] tag:0];
nav1.tabBarItem = item;
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = [NSArray arrayWithObjects:nav1, nil];
//
[nav1 release];
above code is in appdelegate for initial set up of nav + tab controller
SecondScreenViewController *sVC = [[SecondScreenViewController alloc] init];
sVC.title = #"Screen 2";
[self.navigationController pushViewController:sVC animated:YES];
[sVC release];
above is the code in the search view controller that loads the second screen / viewcontroller to the nav controller. But the back button at the top of screen 2 has the word screen 2 in it and when i press it once it reloads itself and then the back button says search (which is the title of first screen) . this time pressing it brings it back to the first screen.
Im just confused why the back button displays the view controllers own title name and reloads itself. I dont have any other code in these screens really, they are just blank screens with labels displaying which screen is there while i learn how to use it correctly
In the Apple Docs for UINavigationController for the designated initializer
- (id)initWithRootViewController:(UIViewController *)rootViewController
it is stated that:
Every navigation stack must have at least one view controller to act as the root.
I would recommend trying to initialize your UINavigationController with a rootViewController.
TiltedWindmill, I've experienced that problem before. In my case, in my head, I wanted to do this:
( > = pushing view controller )
Start at MapViewController > Details About An Attraction for a clicked pin on the map > MapViewController > Then pushing another DetailsViewController.
In my MapViewController, this view controller was registered for a notification. Theoretically, I thought I was navigating like this Map > Details View Controller > Map > Details View Controller. The thing was, whenever I tapped on the pin on the map, the Notification was fired and both copies of MapViewController that was on the navigation stack responded to the notification.
As a result it pushed two copies of the same DetailsViewController. So the real navigation was like this:
Map > Details View Controller > Map > Details View Controller copy1 + DetailsViewController copy2
*> = Second details view controller was pushed ontop of the previous one but not visible to the eye.
When I went to press the back button, it popped DetailsViewController copy2 and showed the same view controller (DetailsViewController copy1).
I fixed it by telling my MapViewController to unsubscribe from the notification on the event viewDidDisappear.
Not sure if you understood that :P
I'm building an application based on the Utility template from Xcode, to which I have added some more views. My application structure would be as follows:
MainView (the app menu)
Flip-side view (a calculator)
UINavigationController
Settings view
viewDiDLoad: UITabBarController
- Tab1 view (options)
- Tab2 view (information text)
I can navigate correctly from my MainView to my Flip-side view, which is also the root view of the Navigation Controller. From my Flip-side view, I push a second view of my Navigation Controller (Settings view) that is configured to show an UITabBarController, with two tabs, as soon as it loads (with viewDidLoad).
If I remove the UITabBarController, I can return with no problems to my Flip-side view using "popViewController" from my Settings view. The problem comes if I load the UITabBarController in viewDiDLoad in my Settings view... the tabs work perfectly, but I'm not able to return to my Flip-side view (root view of the Navigation Controller) anymore.
I CAN return if I use the Navigation Bar of the Navigation Controller, but I want to configure my own buttons and have the Navigation Bar hidden.
So far I've tried the following methods:
[self.navigationController popViewControllerAnimated:YES];
[self.navigationController popToRootViewControllerAnimated:YES];
[self.navigationController popToViewController:FlipSideViewController animated:YES];
But they don't seem to work. The first two just do nothing (the screen remains as it was), and the third one does not recognize the "FlipsideViewController" (maybe because it's a delegate of the MainViewController?).
Is there a way to check what is exactly doing the "back" button of the Navigation Bar if I activate it?
Should I be using delegates?
Can I call a popViewController method in my Settings view from any of the two Tab views?
This is my Flip-side view:
- (IBAction)showSettingsView {
SettingsViewController *controller = [[SettingsViewController alloc] initWithNibName:#"SettingsView" bundle:nil];
controller.title = #"Settings";
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
This is my Settings view:
- (void)viewDidLoad {
[super viewDidLoad];
tabBarController = [[UITabBarController alloc] init];
Tab1ViewController* vc1 = [[Tab1ViewController alloc] init];
Tab2ViewController* vc2 = [[Tab2ViewController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, nil];
tabBarController.viewControllers = controllers;
[self.view addSubview:tabBarController.view];
}
And the method to return in one of the Tab views:
- (IBAction)backFromTab1View {
[self.navigationController popToViewController:FlipSideViewController animated:YES];
}
Thanks very much and sorry if the question is too basic!
I actually solved the problem creating my own UINavigationBar in the Settings view and using:
[self.view insertSubview:tabBarController.view belowSubview:myNavigationBar];
That inserts the rest of the view below the Navigation Bar and I still can use it to configure a button which pops the view and return to the previous screen.
It took me a while to realise the differences between "addSubview" and "inserSubview + belowSubview". Sorry about that!