Objective-c How properly mange multiple views and controllers - objective-c

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];

Related

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];

Several Navigation Controllers in an app

I have an app with navigation controller, but my app also has a simple separate view which is not a navigation controller part. And what I want to do is to add a brand new navigation controller to this view.
For my first navigation controller I used this code in my AppDelegate:
UINavigationController *navigationController = [[UINavigationController new] initWithRootViewController:viewController1];
navigationController.viewControllers = [NSArray arrayWithObject:viewController1];
self.window.rootViewController = navigationController;
But which code I should use, if I want to create a new Navigation Controller ?
Thanks !
UPDATE:
So, I made some pictures:
One the first pic there is a navigation controller (which is declared in AppDelegate). And It contains an info button. Then, when we press the button we move to another view (pic 2). And its just a navigation bar in this view, not an navigation controller. I wanna add a navigation controller, not a navigation bar in this view, so users will be able to use UITableView easily
We would need to know a little more about your intended view hierarchy, and application flow. But in the code you're posting, I'm not sure what is going on. Why not just:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController1];
self.window.rootViewController = navController;
That said, you would create other UINavigationControllers exactly the same way.
Update:
When you press the info button on the first view, you could present the navigation controller modally I think.
- (IBAction)infoButtonAction:(id)sender;
{
// InfoTableViewController is the controller with Instructions, Contact, and something else
// my Russian isn't so good.
InfoTableViewController *tableController = [[InfoTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableController];
navController.modalPresentationStyle = UIModalPresentationFormSheet; // or whatever
[self presentModalViewController:navController animated:YES];
}
Note that I'm not dealing with memory management because I don't know if this is ARC or not. Is that how it should behave?

How to save data when changing views

I hope an easy question (but I can't solve it :)) I have 2 views, On view 1 I have UILabels that I change the text on with a button click, if I navigate to view 2 and then go back to view 1 the text is reset.
Is there any way to retain the text on the label when the view is changed?
Originally I used:
-(IBAction) napButton:
(id) sender{ nap *nap1 = [[nap alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:nap1 animated:YES];
this performed a simple view switch. With the suggestion below I changed this to:
-(IBAction) napButton:
(id) sender{ nap *nap1 = [[nap alloc] initWithNibName:#"nap" bundle:nil];
[self.navigationController pushViewController:nap1];
[nap1 release]; } }
The button performs no action and I get warning UINavigationController may not respond to -pushViewController
use UINavigationController. In a memory constrained device this is the best way to push or pop new views while preserving data or state in previous view.
An instance of UINavigationController can be created either in code or in an XIB file with relative ease. It’s thought of as a stack: it has a root view controller, and then new view controllers can be pushed onto the stack (often when the user taps on a row in a table) or popped off the stack (often by pressing the back button).
There are 4our methods are used to navigate user through the stack:
– pushViewController:animated:
– popViewControllerAnimated:
– popToRootViewControllerAnimated:
– popToViewController:animated:
For example if you want to move from view1 to view2, you need to do this from view1 -
SecondViewController *secondView = [[SecondViewController alloc]
initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondView];
[secondView release];
to move back to the previous state, i.e. from view2 to view1, you need to do this from view2 -
[self.navigationController popViewControllerAnimated:YES];
This should solve your problem in the most efficient way.

TabBarController inside NavigationController

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.

Switch views on the same tab in a tab bar WITHOUT using a navigation controller

I am looking for a way to switch the current view in a tab container to another, all within the same tab and not using a navigation controller.
I have tried something like this:
FooViewController *fooViewController = [[FooViewController alloc] initWithNibName:#"FooViewController" bundle:nil];
self.view.window.rootViewController.view.window.rootViewController = fooViewController;
[fooViewController release];
And this:
FooViewController *fooViewController = [[FooViewController alloc] initWithNibName:#"FooViewController" bundle:nil];
[self.view removeFromSuperview];
[self.view addSubview:fooViewController.view];
[fooViewController release];
To no avail.
Any ideas?
The method I used was to create a subclass of UIViewController that I used as the root view of 3 child view controllers. Notable properties of the root controller were:
viewControllers - an NSArray of view controllers that I switched between
selectedIndex - index of the selected view controller that was set to 0 on viewLoad. This is nonatomic, so when the setSelectedIndex was called it did all the logic to put that child view controller in place.
selectedViewController - a readonly property so that other classes could determine what was currently being shown
In the setSelectedIndex method you need to use logic similar to:
[self addChildViewController: selectedViewController];
[[self view] addSubview: [selectedViewController view]];
[[self view] setNeedsDisplay];
This worked really well, but because I wanted to use a single navigation controller for the entire application, I decided to use a different approach.
I forgot to mention you will want to clear child view controllers every time you add one, so that you don't stack up a ton of them and waste memory. Before the block above call:
for (UIViewController *viewController in [self childViewControllers])
[viewController removeFromParentViewController];