I have an application in which I am trying to dynamically switch the tabbar tab through the code. The tab switches properly. When I click on any tab the didSelectController method of the tab is called and my problem is when I click on any tab the tab on which I am performing switching of views, its navigation bar disappears and its tabbar image and title also disappears.
This is my code. In the appdelegate:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSString *clockswitch = [[NSUserDefaults standardUserDefaults]objectForKey:#"clock"];
UIViewController *desiredController = nil;
if ([clockswitch isEqualToString:#"digital"]) {
desiredController = [[DigitalClockViewController alloc] initWithNibName:#"DigitalClockViewController" bundle:nil ];
}
else {
desiredController = [[AnalogClockViewController alloc]initWithNibName:#"AnalogClockViewController" bundle:nil];
}
NSMutableArray *controllersCopy = [self.tabBarController.viewControllers mutableCopy];
[controllersCopy replaceObjectAtIndex:0 withObject:desiredController];
self.tabBarController.viewControllers = controllersCopy;
}
You code is changing the order in which your view controllers appear in the tab bar, not changing the selected view controller as you seem to wish. This may result in the same view controller appearing twice in the bar, which may have unintended side effects.
Use selectedIndex or selectedViewController to change the selection. You want to select one of the controller that is already there, not alloc/init a new one; and, as Johannes has said, the entry in the list of controllers with be a UINavigationController with a rootViewController that is an instance of your class (isKindOf:).
If you want each view controller within your tab bar controller to have a navigation bar, you have to "wrap" each view controller in a navigation controller and then but the navigation controller into the viewControllers property of your tab bar controller. You wrap it like so:
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:desiredController];
if ([clockswitch isEqualToString:#"digital"])
{
desiredController = [[DigitalClockViewController alloc] initWithNibName:#"DigitalClockViewController" bundle:nil ];
navigationController=[[UINavigationController alloc] initWithRootViewController:desiredController];
[self presentModelViewController:navigationController animated:YES];
[navigationController release];
[desired... release];
}
else {
desiredController = [[AnalogClockViewController alloc]initWithNibName:#"AnalogClockViewController" bundle:nil];
...//same code
}
Related
In a common iPhone configuration, my application's main window is a tab bar controller that contains multiple UINavigationController. My stumbling block now is pushing and changing controllers simultaneously: it appears that I can do both sequentially, but I have to press the tab again to have the view updated.
For example, I'm on tab 1, and I have a button that will load a new view on tab 2 that I want to present right away. Code for that is
tabController.selectedViewController = myListsController;
EditListViewController * editController = [[EditListViewController alloc] initWithList:l];
[myListsController.navigationController pushViewController:editController animated:YES];
With this code, the new tab is presented, but I don't see the new view. Can this be done?
If you have only 2 tab views (and myListsController.navigationController is the root of your 2nd tab), you could do it like this:
UINavigationController *nc = myListsController.navigationController;
EditListViewController *editController = [[EditListViewController alloc] initWithList:l];
[myListsController.navigationController setViewControllers:
[NSArray arrayWithObjects:[[nc viewControllers] objectAtIndex:0],editController,nil]];
NSMutableArray *vcs = [[tabController viewControllers] mutableCopy];
[vcs replaceObjectAtIndex:1 withObject:nc];
[tabController setViewControllers:vcs];
[vcs release];
[self.tabController setSelectedIndex:1];
Try
-(void)viewWillAppear:(BOOL)animated {
//your code
}
in you Viewcontroller class.
I have a very simple question. I have a view controller. In the view controller, i have added few buttons. On button click I have to start a tab bar controller (each of which has navigation controller).
Code Snippet:
- (IBAction) pushNewsAlertsController:(id)sender {
//Create a navigation controller
UINavigationController *FirstNavController = [[UINavigationController alloc] init] ;
//create the view controller (table view controller)
FirstViewController *firstViewController = [[FirstViewController alloc] init];
[FirstNavController pushViewController:firstViewController animated:YES];
//Create a navigation controller
UINavigationController *secondNavController = [[UINavigationController alloc] init] ;
//create the view controller (table view controller)
SecondViewController *secondViewController = [[SecondViewController alloc] init];
[secondNavController pushViewController:secondViewController animated:YES];
// Set the array of view controllers
tabBarController.viewControllers = [NSArray arrayWithObjects:firstNavController, secondNavController, nil] ;
//Add the tab bar controller's view to the window
[self.view addSubview:tabBarController.view];
}
I am able to add the tabviews and navigation controller. The problem is I am unable to get back to the main view once the button is clicked.
Can anyone guide me on how to get back to the previous view so that I can click other buttons.
In this case, I would consider presenting the tab bar controller modally. It's a cleaner way of organizing your views in the same way the user interface is organized. You can just dismiss the modal presentation to go back to the previous view. Read View Controller Programming Guide for iOS about similar advice and examples.
Not sure if I get what you are trying to do, but if you want the tab bar controller view to disappear again, the only way would be the inverse of
[self.view addSubview:tabBarController.view];
which could be
[tabBarController.view removeFromSuperview];
I must say it looks like an odd construction you're building, but it may work nevertheless.
I have a root view controller which has few buttons. On click of these button, I shown up a tab bar controller with each controller showing the table view controller. I have achieved this. So basically, for each table view controller I have a dedicated class. To go ahead, I replaced the tab bar controller, and added the segmented controller to the navigation title view.
The question is how can I set the view based on the selected index. I am able to set the navigation title to be segmented control but on select I am unable to set the view.
Below is what i have achieved so far.
Note: What matters is a running code, I would do that code optimization later on. I dont want to hidde views. I want to call different view controller class.
RootViewController class (on click of the button, i call the first view controller. So that I can set the segment controller:
-(IBAction) pushSegmentController: (id) sender
{
NSLog(#"My Location Button being clicked/touched") ;
FirstViewController *firstViewController = [[FirstViewController alloc] init] ;
[self.navigationController pushViewController:firstViewController animated:YES];
// Releae the view controllers
[firstViewController release];
}
IN FirstViewController class:
-(void)viewDidLoad {
[super viewDidLoad];
NSArray *viewControllers = [self segmentViewControllers];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Table1", #"Table2"]];
self.navigationItem.titleView = segmentedControl;
[self.segmentedControl addTarget:self
action:#selector(indexDidChangeForSegmentedControl:)
forControlEvents:UIControlEventValueChanged];
self.segmentedControl.selectedSegmentIndex = 0;
}
-(void)indexDidChangeForSegmentedControl:(UISegmentedControl *)aSegmentedControl {
NSUInteger index = aSegmentedControl.selectedSegmentIndex;
if(index ==0) {
UIViewController *table1Controller = [[AustraliaViewController alloc] initWithStyle:UITableViewStylePlain];
**???? HOW SHOULD I SET THE VIEW OVER HERE... AS ITS A PART OF THE NAVIGATION CONTROLLER**
}
else { }
}
Note: I have tried using this option:
[navigationController setViewControllers:theViewControllers animated:NO];
But this option doesnt give me the right result. How should I go ahead with the same as I want to call a view controller class and set its view based on the selected index.
You probably don't want to have one view controller with different views depending on the button index, especially since you already have view controllers for your different screens.
If you want the table view controller to be pushed onto your navigation controller, so it will have a back button that gets you back to FirstViewController, use
-(void)indexDidChangeForSegmentedControl:(UISegmentedControl *)aSegmentedControl {
NSUInteger index = aSegmentedControl.selectedSegmentIndex;
UIViewController *newViewController = nil;
if(index ==0) {
newViewController = [[AustraliaViewController alloc] initWithStyle:UITableViewStylePlain];
} else {
newViewController = [[YourOtherViewController alloc] initWithStyle:UITableViewStylePlain];
}
[self.navigationController pushViewController:newViewController animated:YES];
}
If you'd rather have it slide in from the bottom and you want to handle setting up all necessary user interface (e.g. a dismiss button), replace that last line with
[self presentModalViewController:newViewController animated:YES];
What about?
self.view = table1Controller;
or
[self.view addSubview:table1Controller];
I just saw one more mistake you have done. You are allocating a UIViewController, but initializing it like a tableViewController(with initWithStyle).
If it's a subclass of UITableViewController, alloc it with that, not UIViewController.
I have a view controller alike contacts in iPhone. The code is something like this,
tabBarController = [[UITabBarController alloc] init];
friendsVC = [[RemittanceFriendsVC alloc] initWithNibName:#"RemittanceFriendsView" bundle:nil];
friendsVC.friendsArray = [[RemittanceModel getInstance] friends];
UINavigationController *friendsNVC = [[UINavigationController alloc] initWithRootViewController: friendsVC];
[controllers addObject:friendsNVC];
tabBarController.viewControllers = controllers;
The RemittanceFriendsVC is UITableViewController, clicking on a cell takes to details view. I have 'modal' variable set in the ViewController (VC)to know if its loaded as modal or not. Since its part of a tab bar item, (non modal view) it works fine. But when I am loading it as modal VC, when I click on a table cell, I want to dismissmodalview, but it did not dismiss the modal view.
In the friendVC this is not working,
-(void) didPressCancelButton {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
What I wanted to do is, use the same VC as a tab bar item and sometime as a modal VC. Isn't it possible?
okay, it was the problem with the
[self.navigationController dismissModalViewControllerAnimated:YES];
it should be,
[self dismissModalViewControllerAnimated:YES];
Then it works fine.
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!