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.
Related
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
}
So before I've managed to work with TabBarViewControllers and create an application using them. However every time I do so the view acts as my main view. This time around I want my TabBarView to be my second view in my application
E.g
First window has a bunch of buttons, when I click one of these buttons I want the second view to show up. This view includes a TabBarViewController.
The farthest I've gotten is to have the button show a view but for some reason it won't show my TabBar view!
Here's the code for my button
- (IBAction)showEvents:(id)sender {
EventsViewController *controller = [[EventsViewController alloc] initWithNibName:#"EventsView" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
}
Any of you guys able to help?
Can't you just in the EventsViewController add the following code in viewDidLoad:
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = [NSArray arrayWithObjects: vc1, vc2, ..., nil];
Anyway, I found a solution and it was actually quite simple. After creating the Outlet for the TabBarController and linking it together with File's Owner all I had to do was add
self.view = tabViewController.view;
On the viewDidLoad method
I'm creating an application that, when the user selects a project in a table, displays a view with a tab bar at the bottom. I'm using this code:
- (id)init
{
[super initWithNibName:nil bundle:nil];
tabController = [[UITabBarController alloc] init];
// Create all view controllers to be included in the tab bar
SummaryViewController *summaryController = [[SummaryViewController alloc] init];
ImagesViewController *imagesController = [[ImagesViewController alloc] init];
// Make an array containing the view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:summaryController, imagesController, nil];
[summaryController release];
[imagesController release];
// Attach them to the tab bar controller
[tabController setViewControllers:viewControllers];
[self.view addSubview:tabController.view];
return self;
}
With the end result being the tab bar at the bottom appearing cut off around half its height. I'm guessing it's somehow related to the navigation controller at the top (link to image).
Any help in solving this mystery would be greatly appreciated!
I believe the problem here is that you're adding the UITabBarController as a subview of another UIViewController. UITabBarController descends directly from UIViewController.
Instead of creating this view controller to hold it, you should just create the tab bar controller, configure it and push that onto your stack.
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!
I'm relatively new to objective c but not programming and am stuck with my iphone app.
I created a nav based app with both a navbar and a tab bar controller. I set the tab bar as the root controller. I'm able to switch between each tab without any issues to various UIViews and UITableViews.
My issue is that in one of my UITableViews that I call from the TabBarController, didSelectRowAtIndexPath function is suppose to display a new UIView. The below code does not give any errors and runs fine but does not show the new Nib.
if(newViewController == nil) {
NSLog(#"yes nil");
BookViewController *aNewViewController = [[BookViewController alloc] initWithNibName:#"BookOptionView" bundle:nil];
self.newViewController = aNewViewController;
[aNewViewController release];
}
BookAppDelegate *delegate = (BookAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.appNavBar pushViewController:newViewController animated:YES];
Now when I do the below, it works fine but it gets rid of the nav and tab which I'm assuming because its a modal call instead of pushing the view controller.
BookViewController *screen = [[BookViewController alloc] initWithNibName:#"BookOptionView" bundle:[NSBundle mainBundle]];
screen.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:screen animated:YES];
[screen release];
Any ideas why I can't get the View Controller to push correctly? In my application delegate file, I declared an AppNavBarController object (inherit from UINavigationController) called appNavBar.
Any help would be appreciated!
If you want to present your view as a modal view with nav controller, you can do it as below:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];
[self presentModalViewController:navigationController animated:YES];
Also, from what I see, you have your navcontroller in your appdelegate. So I guess you are using a global navcontroller for all your tab views, which ideally shouldn't be the case. Your navcontroller should be within your tab controller and preferably you need to have different nav controllers in different tabs.
I actually found my answer. I'm not sure I understand why my code above doesn't work but the following accomplishes what I want:
[self.navigationController pushViewController:newControllerName animated:YES];