For my application, I have one UIViewController and about 8 UIViews. The views are all properties of the view controller, linked via the Interface Builder (IBOutlet). So when the view controller loads, all of the views are also loaded, and I have built-in methods to switch back and forth between the different views.
Is it bad to have them all linked to one view controller -- should each view have its own view controller? Because they're all linked to one, I'm assuming they're all in memory at the same time and are never released because the view controller itself is never released.
What is the standard practice for this?
If you have a bunch of views that will always be on-screen at the same time, then they should be controlled by one UIViewController.
If you have a bunch of views that will alternate between completely controlling the screen, then each view should have its own UIViewController.
If you have a single view that's always on-screen that delegates part of the screen to another view that can change, then you should have a UIViewController to manage the main view as well as one UIViewController per subview.
(Any time you have a view that can sometimes be on-screen and sometimes be off-screen, you should probably be using a UIViewController to manage its lifespan.)
Related
iOS 5 introduces the concept of custom container view controller and provides API like addChildViewController. Question: can you add a view controller as a child and still present it using presentViewController? Does doing the latter automatically make it a child view controller of the presentingViewController?
That's not how it's supposed to be used.
The parent/child relationship is for when a view controller has subviews that are managed by their own view controllers, for example a UITabBarController, where the parent view controller draws the tabs and the child view controllers draw the content of each tab.
If you present a view controller using presentViewController, it generally takes over the whole screen, or appears in a modal so that the presenting view controller is no longer in control. In that scenario there's no reason for the presenter to be the parent because it doesn't need to cooperate with the presented controller - it just gets out of the way until the presented controller is dismissed again.
Why is it that you wanted to do this? If it's just so that the view controllers have a reference to one another and can pass data, there are other ways to do this (e.g. the delegate pattern, NSNotifications, or even just a property linking the two).
When Switching between two view controllers, what's the difference between addSubView or using a navigation controller and using pushViewController?
In my app, I have a few set up screens in the beginning before a game calculator starts (which has a lot of view switching in between, and a lot of ViewControllers are reused).
In that case, should I set up a navigation controller in the AppDelegate or in the RootViewController, or just use addSubView in the first few set up screens and add a navigation controller where my calculator views start after the set up screens?
The difference is that with addSubiview, you add a view to another, which therefore will contain it. The navigation controller actually manages a stack of VC, in which the next view isn't included in the previous.
Another diference is about parameters, addSubview will accept a view as argument, while the other will accept a view controller.
Typically, a navigation controller is used when displaying hierarchical content (in a table view most of the time), that allow the user to go deeper in details, or getting back to previous levels.
I'm a bit confused as to implementing custom view controllers. I have a view that I want to have slide down from the top of the window. The view has three buttons on it. When the button for the view to drop is tapped the view drops. And when tapped again the view slides up/goes away. I have the drop down view saved as a nib file. Would this be the best method for implementation? Or should I have the view in the main view's nib?
And could I get some direction on how I should set it up?
The usual pattern has each of the view's stored in their own XIB file and associated with their own view controller objects. You then alloc/init the new view controller and point it to its XIB and present it modally. Once its presented, its VC responds to its actions and interacts with the model and updates its own views. You can then dismiss that view controller and its views to revert back to the parent view controller.
I have noticed a pattern mentioned in SO where people alloc/init a child VC and then within their present VC they addSubview the newVC.view, but that just seems pretty unusual to me.
If you just have a subview that is being animated down to partially cover the screen, perhaps it doesn't warrant its own VC since, as I think I'm understating your usage, its actions would map to your current VC. In that case, I would either create its contents programmatically or just as another view in the XIB for your first VC and animate that down when needed.
I'm getting confused on view controllers and would love a straight example. Here's the preamble:
I have a UIViewController with a matching .xib.
By default IB gives me a single View in the Document window.
I can make it appear by telling my UIWindow to addSubview:controller.view and bringSubviewToFront:controller.view
Here's the questions:
Should I add another View to the ViewController in IB? Or is there a better, programmatical way?
How do I tell the ViewController to switch between the Views?
From the ViewController downward, what does the code look like to achieve this?
I'm trying things but just making a mess so I thought I'd stop and ask...
Note that every button, label, image, etc. in your main view controller is actually a view in itself, however I've interpreted your question to mean that you want to manage multiple full-screen views or "screens". Each screen should have its own view controller to manage it. So to get the terminology right, a view-controller is an object that manages a single full-screen view (or almost full screen if it's nested inside a navigation controller or tab bar controller for example) and a view is the big area managed by the view controller as well as all the sub-views (images, buttons, labels, etc.) within it (they are all UIView sub-classes). The view controller manages all of them on that screen, if you want another screen/page then you should create a new view controller to manage it.
The root view controller (the one you add to the window) can be a plain old normal view controller that you've designed in IB, however it's probably more useful if you use a navigation controller or a tab bar controller and add your designed view controller to that - then you can push additional view controllers as needed.
Another way (if you don't want navigation or tab-bar style) would be to transition to other view controllers directly in the main window using whatever transitions you like (or just replace the old one). We'll leave that for now though.
Any sub-views of your main view controller (the one you've designed in IB) will be automatically loaded from the nib file, but you can also add your own views programatically if you want (typically you would use one or the other, i.e. nibs or programatically, but you can mix and match if you want). To do it programatically, override loadView in the view controller and then call [super loadView]; then do [self.view addSubView:myOtherView]; (create the myOtherView first of course). Note that the first time .view is accessed on your view controller, it actually calls loadView to create the view, so inside loadView it's important to call [super loadView]; before trying to access self.view :D
To switch between views, using the navigation or tab bar controllers makes it very easy. So put your main view controller inside (for example) a navigation controller and put the navigation controller in the window, so you've got window->navigationController->myController. Then from an action method in your view controller (you can hook up the action methods in IB), for example when an "about" button is pressed do this:
- (void)doAbout
{
// Create the about view controller
AboutViewController* aboutVC = [AboutViewController new];
// Push the view controller onto the navigation stack
[self.navigationController pushViewController:aboutVC animated:YES];
[aboutVC release];
}
Note that the about view controller is created programatically here - if your about view is designed in IB then instead use initWithNibName:bundle: to create it.
And that's how you manage multiple screens.
Is it possible to have a single iPhone screen with its view loaded from a xib by that screen's UIViewController, but then another UIView within that screen with content loaded from a separate xib file? If so, is it possible to have that nested view's events handled by a separate custom UIViewController subclass from the rest of the screen? If both of these things are possible, are they also advisable?
It is possible. Apple suggests against having more than one UIViewController active on screen at once, so they would advise against. I would suggest only doing it if the reason for the second view controller is navigation or modal.
A view controller with the purpose of loading other view controllers, like a navigation controller, needs some screen space for itself and uses the rest to load another view controller. That is fine. The criteria here is that only one controller is presenting content while the other is presenting navigation.
A view controller could load another view controller to perform some limited task like selecting an item from a list or entering some text. The second view controller might only fill part of the screen. The criteria here is that the one controller behaves modally and will only be displayed long enough to get some user input.
As for the general case of splitting the screen between two view controllers that are presenting content, the Apple suggestion is that you have a single class derived from UIViewController manage the views. If the view is complex enough to warrant other controllers, then derive them from NSObject and have the master view controller manage the child controllers along with the views. The child controllers would have the master controller as a delegate, and the master controller would pass views to the child controllers to manage but not own.