TabBarController inside NavigationController - objective-c

Imagine that we have multiview apllication which is controlled by Navigation Controller. We go from the first view to second by using pushViewController method and that's not a problem but then we need to move to the third view. And the third one is a view which looks like a TabBar. How do we do that? The third view is supposed to be controlled by TabBarController, isn't it?
So how to pass the control? I declared an outlet UITabBarController * tbc and connected it to TabBarController in xib file and then i tried this in viewDidLoad:
tbc = [[UITabBarController alloc]init];
and it shows nothing.
Your help is highly appreciated

It's a bit wierd. Its more standard to have a tabBarController that switches views and some of those views may be navigation controllers. But ...
Create the UITabBarController and push it.
NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
// create someView
[viewControllers addObject:someView];
// create someView2
[viewControllers addObject:someView2];
UITabBarController *tabController = [[UITabBarController alloc] init];
[tabController setViewControllers:viewControllers];
[[self navigationController] pushViewController:tabController animated:YES];
Then, from the tabBarContoller view, based on some action, you can choose to pop it:
[self.navigationController popViewControllerAnimated: NO];

You can wire it up in the storyboard editor in the latest version of Xcode.
However, since this is very much non-standard use of the controls, you would need a very good reason as to why you would want a UI like this.
And even then, Apple's review process might turn your app down if the interface is clunky.

Related

Can we put navigationcontroller in MasterView in iPad Application?

I have worked mostly on iPhone apps. Now I need to build an iPad app. In that I need to put NavigationController in the MasterView of the Master Detail View of the iPad as we do in the UITableView in the iPhone. I mean when user selects a particular row it should navigate to another tableview with newly filled data. and user can go to the previous by pressing back button. Also On each selection I need to make change of image in the detail view.
I dont have any idea to achieve this.
Please provide any suggestions or any sample code for it.
Thanks in advance.
try this in your appDelegate didFinishLaunchingWithOptions method
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil] autorelease];
UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
self.splitViewController = [[[UISplitViewController alloc] init] autorelease];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationControlle, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
This is certainly possible. There are no limitations on what you can display in the master and detail views of a split view controller.
Think of the split view as merely a view that displays two of your view controllers. They can contain anything.
If I understood what you're trying to achieve correctly then what you want to do is create a View Controller with a UITableView which will display the data in the left column. This View Controller should also have a UINavigationController which will push another view controller when you select something in the table.
So far, so good. Nothing has changed in the detail view since it in reality isn't aware of or connected to the master view in any way. When the user has moved enough steps down in the master view, and you want to change the detail view - then you can set the viewControllers-property of the navigation controller to update the detail view with whichever view controller you want to display.
Yes you can. Apple has provided a sample code called MultipleDetailViews
It shows how communication is done between master and detail using delegation.
See these Tutorials :-
http://www.icodeblog.com/2010/04/05/ipad-programming-tutorial-hello-world/
http://www.raywenderlich.com/1040/ipad-for-iphone-developers-101-uisplitview-tutorial
These will help you.

Switch views - UIViewController to UITabBarController

I have made a very simple Navigation based app (UIViewController). The view has a single button on the Main RootViewController.
Next, I made 2 classes: TabOneViewController, TabTwoViewController. All good. I then created a new Class TabBarViewController. I opened up the NIB file and dropped on a ``UITabBarController onto it. The two tabs it creates in it by default were assigned (respectively) to my TabOne and TabTwo view controllers.
strong text
Then in my TabBarViewController, I made an IBOutlet for a UITabBarController, synthesized it etc etc. I linked it up in Interface builder via the "files owner".
In the RootViewController, I linked the button to my "pushView" method, and in this pushView method, I have the following code:
- (IBAction) pushView {
TabBarViewController *controller = [[TabBarViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
The end result is it DOES push a view, but I cannot see the tab bar at the bottom, let alone any of the pages I've added to the controller.
What am I doing wrong? Why can't I link it in IB?
I am not 100% sure if that's allowed.. because you already have one tabBarController as rootViewController, and you dropped one more tabBarController as first tab controller, tabs ll overlap, considering amount of real estate you have on your iPhone, it make sense to not allow a tabViewController inside another
First, you need to allocate your view controller with your nib:
TabBarViewController *controller = [[TabBarViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
Secondly, in IB, click the UITabBarController and go to the identity inspector and make sure you select your custom class. That said, unless you are overriding or adding some functionality you probably don't need the custom class at all, simply use a UITabBarController directly:
UITabBarController *controller = [[UITabBarController alloc] initWithNibName:#"YourNibName" bundle:nil];

Objective-c How properly mange multiple views and controllers

I have an aplication which initially there's a TabBarController, each tab is a ViewController and every one has a button which calls other controllers.
So how am I supose to structure this? Having one main rootviewController (if so, how?)? Or calling in the appdelegate only the tabBarController and in each the viewControllers inside the tab call the other controllers?
What's the best way so I can advance, go back and transition views nimbly?
Don't know if I made myself clear...
Thanks guys.
Generally you will start with the Template called "Tab Bar Application" and as of Xcode 4 starts by loading the MainWindow Nib, which hold a tab bar and the tab bar is set up in IB to have 2 view controllers, called "FirstViewController", and "SecondViewController"...
You can follow that pattern if it suites you, otherwise you may want to start with a view based application and add your own tab bar. I personally find it to be easier to control the tab bar, through the UITabBarDelegate, especially if you plan to do anything slightly esoteric.
Edit:
Basically one of two ways, if you plan to load a Navigation controller stack, or a single modal view.
1)
ThirdViewController * controller = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
UINavigationController * myNavigationController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentModalViewController:myNavigationController animated:YES];
[controller release];
[myNavigationController release];
2)
ThirdViewController * controller = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
[self presentModalViewController:controller animated:YES];
[controller release];
either way get back to the Tab environment by calling the following on the view controller that is calling present modal.
[self
dismissModalViewControllerAnimated:YES];

Using setViewController from UINavigationController on iPhone doesn't behave properly

I'm having a problem with an iPhone App using UINavigationController. When I'm using pushNavigationController, it works fine. The iPhone does its animation while switching to the next ViewController. But when using an array of ViewControllers and the setViewControllers method, it has a glitch in the animation which can grow into a clearly visible animation bug.
The following snippet is called in the root ViewController. Depending on a condition it should either switch to ViewController1, or it should directly go to ViewController2. In the latter case the user can navigate back to vc1, then to the root.
NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack
[viewControllers addObject:self];
// add first VC
AuthentificationViewController* authentificationViewController =
[[[AuthentificationViewController alloc] initWithNibName:#"AuthentificationViewController" bundle:nil] autorelease];
[viewControllers addObject:authentificationViewController];
if (someCondition == YES)
{
UserAssignmentsListViewController* userAssignmentsListViewController =
[[[UserAssignmentsListViewController alloc] initWithNibName:#"UserAssignmentsOverviewViewController" bundle:nil] autorelease];
[viewControllers addObject:userAssignmentsListViewController];
}
[self.navigationController
setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];
As you can see I'll add the first and maybe the second VC to the array, finally setting the navigationController stack with animation. This works properly if I only add the first controller. But in the case where the animation should go to the 2nd controller, the navigation bar's title won't be "flying in". Instead there is an empty title until the animation is finished. And, even worse, if I replace the navbar title with a custom button, this button will be displayed in the upper left corner until the animation is finished. That's quite a displaying bug.
I tried to use a workaround with multiple pushViewController methods, but the animation doesn't look / feel right. I want the navigation to do its animation in the same way as pushViewController does. The only difference here is, that I don't add a VC but set the whole stack at once. Is there another workaround here, or could this be considered as a framework's bug? I thought about using only pushNavController for VC2, then somehow insert VC1 into the stack, but that doesn't seem possible.
Thanks for all hints and advices. :-)
Technical data: I'm using iOS 4.2, compiling for 4.0.
Finally I found the solution. The mistake was that the new top-level NavigationController has not been initialized and loaded properly until the animation is done. In my case, UserAssignmentsListViewController has a viewDidLoad method that will not be called until animation is done, but it sets the navigation title (here: a UIButton). Therefore the animation fails.
The solution is to refer to an already initialized view controller when it comes to pushing it to the stack. So initialize our top-level VC somewhere:
// initialize our top-level controller
ViewController* viewController2 = [[[ViewController alloc]
initWithNibName:#"ViewController" bundle:nil] autorelease];
Then when pushing two or more VCs to the stack, the top level one is already initialized and the animation works (following the example from my original question):
NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack, too
[viewControllers addObject:self];
ViewController* viewController1 = [[[ViewController alloc]
initWithNibName:#"ViewController" bundle:nil] autorelease];
[viewControllers addObject:viewController1];
if (someCondition == YES)
{
[viewControllers addObject:viewController2];
}
[self.navigationController
setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];

Create UINavigationController programmatically

Just because I am unable to find a secure way (in a sense that it can be rejected by Apple guys) to customize UITabbar, in particular UITabBarItem I am trying some workaround.
I have a main view on which I recreate a kind of UITabBar, a normal view with two buttons inside. This is (roughly) the current hierarchy:
-MainView
--placeholder(UIView)
--fakeTab (UIView)
What I want to do is, after tapping a button in fakeTab, build a UINavigationController and add it to "placeholder" view so that the fakeTab remain on top and the whole navigation happens on the placeholder level.
I already tried with this piece of code in the method that it's intercepting tap button, and it works, I can see the ipvc.view added to placeholder.
IPPlantsViewController *ipvc = [[IPPlantsViewController alloc] initWithNibName:#"IPPlantsView" bundle:[NSBundle mainBundle]];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:ipvc];
UIView *placeholder = [self.view viewWithTag:200];
[placeholder addSubview:ipvc.view];
But later when I call from inside ipvc, then nothing happens:
IPAttributes *ipas = [[IPFactory findPlantByIndex:indexPath.row] attrs];
[self.navigationController pushViewController:ipa animated:YES];
I find the solution myself. What I was doing wrong is to attach the ipvc controller view to placeholder. Instead of doing this:
[placeholder addSubview:nav.view];
and everything works as expected, with my fake tabbar fully customized :-)
But, as a side note, the viewWillAppear seems to be never called.
It would be interesting to know why. I partially solved by making IPPlantsViewController the delegate of the UINavigationController.