Help Creating multiple views with view controllers - iphone

Ok here is what i am trying to do. In my root view controller I have the main view and then inside that view, i have three additional views. (note this is for the ipad).
Here is what I want to do. When the root view loads i want it to load the other three views as well and all have their own view controller.
Here is what I have attempted to far.
In my root controller xib I put in three view controllers and deleted their views. I then plugged into each controller view slot the views i have laid out within my root controller view. I also plugged in the view controller refrences with the ones i set up in rootcontroller.h
In my rootcontroller.m under the viewdidload i tried setting for example.
theViewController = [[ViewController alloc]
initWithNibName:#"AView" bundle:[NSBundle mainBundle]];
but to no avail that did not work

ViewControllers where desgined to use the entire screen, so this case should not happen. However, is very common that you need some complex user interactions inside your views (specially in iPad) to consider the use of a viewcontroller with some child viewcontrollers that encapsulate this logic as you explained above.
What I suggest you is to implement it by code. You could use something like:
-(void) viewDidLoad {
//Create view controllers
viewController1_ = [[ViewController alloc] initWithNibName:#"View1" andBundle:nil];
viewController2_ = [[ViewController alloc] initWithNibName:#"View1" andBundle:nil];
viewController3_ = [[ViewController alloc] initWithNibName:#"View1" andBundle:nil];
//Add the views to your main view
[self.view addSubview:viewController_1.view];
[self.view addSubview:viewController_2.view];
[self.view addSubview:viewController_3.view];
//TODO: Maybe set the appropiate frames?
}
Becareful with the event bypass. As you are embebing your secondary viewcontrollers into the main one, none of the standard events will be passed down to your child controlles (for example: viewWillAppear, shouldAutorotate,... will not be received by your child controllers). Remember to bypass them explecitly if you need them in your child viewcontrollers.
If your views are not correctly created using IB, check that you dont have problems with these event bypass problem.
Hope that helps!

Related

Adding views with controllers to a view with controller - proper way?

I have to add several views (each having own controller) to a main view (with controller). I am following MVC. Should the code to add these subviews be written in view class or controller class? Also, what is proper way,
MyViewController1 *myViewController1 = [[MyViewController1 alloc] init];
[myMainViewController.view addSubview:myViewController1.view];
Or, some other way?
There is another option - container view controller (with addChildViewController method), but that is tough to manage, so I need the simple way.
If you're adding view controllers to the view of another view controller, then you need to use container containment. You can do that in IB with container views. That makes it easier, than making custom container controllers in code.
The Absolute best way is to maintain ViewControllers according to their functionality (ex. one might be dashboardView one might be settingsView). Now when moving from one view controller to another is to use navigationController.
The practice I follow is to declare one navigationController in appDelegate when your app starts and then keep reusing this. Example -
YourAppDelegate *delegate=(YourAppDelegate *)[[UIApplication sharedApplication] delegate];
MyViewController1 *myVC = [[ FLOHome alloc ]initWithNibName:#"MyViewController1" bundle:[NSBundle mainBundle]];
[delegate.navigationController pushViewController:myVC animated:NO];
This is the absolute best way when dealing with viewControllers. navigationController handles whole lot of stuff like memory management, caching views to make them snappy. You could keep pushing viewcontrollers and poping them when you exit from them...

How Can I Use Buttons to Control Navigation in Root View, Instead of Table Cells?

I'm developing my first iPhone app, which is a navigation based one. I want to know how I can use icons/buttons like this app in the root view to control navigation instead of the default table cell view.
I would appreciate some step by step guide since I'm sort of newbie and didn't get how to do this, reading the documentations, or similar questions.
Rather than starting with a Navigation based app, start with a window based app and create an instance of UINavigationController in app delegate (in method appDidFinishLaunching) and set any UIviewController as it's root view controller. You can then do whatever customizations in that view controller
Finally set the navigationController as rootviewController of you application window.
UIViewController *myCustomRootViewController = [[UIViewController alloc] init];
UINavigationController *myNavController = [[UINavigationController alloc] initWithRootViewController:myCustomRootViewController];
[myCustomRootViewController release];
self.window.rootViewController = myNavController;
[myNavController release];
You really need to use google, or anywhere else on Stack Overflow before you ask a question. I found this in a minute. If you're adding to a navigation controller (which is what handles views in a table view), then use – pushViewController:animated: instead of presentModalViewController:animated: And after you push or present a view controller, don't forget to release it if you are not using automatic reference counting.

How to optimize performance in view controller navigation with UISegmentedControl and UITabBarController

On a project I'm working on, the design decision was to use a UISegmentControl at the top, with a UITabBarController on the bottom. The UISegmentControl has 3 choices for 3 different views. Currently, my coworker has added all 3 views to an NSArray when that particular tab is selected, and then based on the UISegmentControl, the view selected gets unhidden, and the other two are hidden. It seems to not follow Apple's guidelines of lazy loading and seems expensive since 3 viewDidLoads (where queries are made to a database) are getting all loaded at once. There is some lag because of it when the tab is selected for the first time, loading all 3 viewControllers at once.
Is there a better way to do this? I saw a simple example with just two viewControllers, and a button that would switch between the two views. That makes sense to me since you always know what your previous view was, and you can remove that view from the superview, present your new one, release your old one. But with 3 choices, I do not know how to keep track of my view hierarchy (since I could be on segment 0, showing view 0, and then go to segment 2, showing view 2). I am not sure how to check for the last view that was shown, and even if that's the best method. I'm thinking that if there is a better option to keep track of this, but still using the segment control, might as well do it now before the project gets more complex. Thanks!
I would suggest creating a root view controller whose job it is to manage the segment control and load the proper VC depending on which button in the segmented control is selected. The root VC's view would have a subView where the segmented control's VC views are inserted. Something like:
- (void)segmentAction:(id)sender
{
NSParameterAssert([sender isKindOfClass: [UISegmentedControl class]]);
switch ([sender selectedSegmentIndex]) {
case 0:
MYViewController1 *vc = [[MyViewController1 alloc] init];
self.segmentVC = vc;
self.segmentSubvew = vc.view;
[vc release];
break;
}
}
One thing people tend to get hung up on is that there needs to be only 1 VC per screenfull of content -- while that was originally what was recommended by Apple, they have since changed this recommendation. So, loading your segment specific VCs inside the SegmentManagerVC is perfectly acceptable.
You could further tweak this design for performance. For example, you could initially load the VC for the default selected segment and then lazy load the other two so they are already available when a different segment is selected. If you take this approach, though, be sure to hook up -didReceiveMemoryWarning to release the two VCs that aren't currently being viewed.
You could push/pop views onto the UINavigationControler stack. This would also support a "back" button if you wanted it.
[self.navigationController pushViewController:self.myVC animated:YES];
Link a method up to the SegmentedControl that pushes the appropriate ViewController when the corresponding segment is selected. The VC with your segmented control inside of it would need a reference to each segment's corresponding VC. viewDidLoad() will only be called once, and only when the view is pushed onto the navigation stack for the first time.
When you change views or want to go "back", you can pop the VC off the stack:
[self.navigationController popViewControllerAnimated:YES];
Is this the type of functionality which you were looking for?
Edit for Clarity
UIViewController References:
Each view will need a reference to the other two view's ViewControllers. This can be done like this: (assume that we are in "View1", and we also have "View2" and "View3":
View2Controller v2Controller = [[View2Controller alloc] initWithNibName:#"View2" bundle:nil];
View3Controller v2Controller = [[View3Controller alloc] initWithNibName:#"View3" bundle:nil];
The reference to self.navigationController should be declared in your app's delegate as:
UINavigationController* navigationController;
It can be initialized as:
[navigationController initWithRootViewController: rootViewController];
The RootViewController
rootViewController is the UIViewController that corresponds to your application's root view (whatever loads on startup). It is declared in the delegate as:
RootViewController* rootViewController;
And initialized as:
rootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];

Add view to a navigation controller on app launch

I have an app that has a UITabBarController, one of the tabs of which is configured for a navigation controller.
Based on certain logic I need to attach a different root view to the navigation controller inside the tab at application launch time.
This is easily done in interface builder however, because I need to figure out what view to attach at launch time interface builder is not much use to me in this situation.
I'm guessing I will need to perform this in the applicationDidFinishLaunching method in my app delegate class by somehow getting the tab I'm interested in, and pushing the view onto it's navigation controller?
How would I go about this?
Thanks.
You're on the right track. In your app delegate's applicationDidFinishLaunching method, you need to look at whatever your condition is and pick the right thing to set as the UINavigationController's root view controller.
I'm guessing this is a login screen or something? And if you have a cached login from an earlier session you don't show it again? Is that it?
If you take a look at that method in your application delegate, you'll see where the default root view controller is getting instantiated and pushed into the nav controller. Just duplicate that code inside an if() statement. I've done this, it's straightforward.
So what I did in my applicationDidFinishLaunching method was:
// get the array of tabs
NSArray *tabBarArray = tabBarController.viewControllers;
// in my case the navigation controller I'm interested in is in the 4th tab
UINavigationController *navigationController = [tabBarArray objectAtIndex:4];
if(someLogic == true) {
ViewController1 *viewController1 = [[viewController1 alloc] initWithNibName:#"View1" bundle:nil];
[navigationController pushViewController:viewController1 animated:NO];
[viewController1 release];
}
else {
ViewController2 *viewController2 = [[viewController2 alloc] initWithNibName:#"View2" bundle:nil];
[navigationController pushViewController:viewController2 animated:NO];
[viewController2 release];
}
Everything working well.

iPhone Sdk: How to add a second UINavigationController?

i created an app from the navigation-based template given by apple. Now i want to add a second navigation controller to my application including a new UITableView. Can anybody show my how to do this? Thanks!
I think this can be done. In your app delegate you normally do something like
[window addSubview:navController.view]. UIWindow is just a UIView. So if you create two UIView ivars in the UIViewController that will contain the two nav controllers you should be able to do a similar thing:
#interface MyViewController : UIViewController
{
UIView* upperView;
UIView* lowerView;
}
etc...
MyUpperRootViewController* myUpperRVC = [[MyUpperRootViewController alloc] init...
UINavigationController* myUpperNavController = [[UINavigationController alloc] initWithRootViewController:myUpperRVC];
[upperView addSubview:navController.view];
[myUpperRVC release];
and something similar on lowerView.
In the root view or subseqeunt views pushed onto the controllers access them in the usual way as if there was one nav controller. [self.navigationController push... should behave normally.
For animating in (and out) the view controllers, just apply the animation to the views - upperView or lowerView. You might want to start with their frames off the visible display and then change them to something visible inside an animation block.