This question already has answers here:
What is the difference between a View and a View Controller? [closed]
(3 answers)
Closed 7 years ago.
Coming to Swift from Delphi, I thought the View represented an app's GUI and the storyboard was a visual representation of the View's underlying code. The ViewController was the one and only object the View interacted with. When a popular tutorial says
In the old days developers used to create a separate interface file
for the design of each view controller.
I'm thinking the "separate interface file" was the View file. But as I learn more, I'm getting confused. Beneath a screenshot of an empty Main.storyboard from a new application, the text says
The official storyboard terminology for a view controller is "scene,"
but you can use the terms interchangeably. The scene is what
represents a view controller in the storyboard ... Here you see a
single view controller containing an empty view.
So I'm seeing a "single view controller," not a view?? Confusion mounts when I note any views(?) displayed on a storyboard are called "View Controllers" in Swift.
So, what's the difference between a View and ViewController? How is a storyboard related? And what object "owns" something like a segue, which exists outside my (flawed) understanding of these concepts?
Take a look at this post - What is the difference between a View and a View Controller?
This described it pretty well for me.
If you don't want to go to the link, here is a great description of the difference between a view and a view controller by Alex Wayne:
A view is an object that is drawn to the screen. It may also contain
other views (subviews) that are inside it and move with it. Views can
get touch events and change their visual state in response. Views are
dumb, and do not know about the structure of your application, and are
simply told to display themselves in some state.
A view controller is not drawable to the screen directly, it manages a
group of view objects. View controllers usually have a single view
with many subviews. The view controller manages the state of these
views. A view controller is smart, and has knowledge of your
application's inner workings. It tells the dumb view objects what to
do and how to show themselves.
A view controller is the glue between your overall application and the
screen. It controls the views that it owns according to the logic of
your application.
Related
This question is related to this.
I am using KLHorizontalSelect for showing tab bar with scroll option. I have dragged new 7 View Controller on storyboard. If I select Popular, popular view controller should get displayed.
Any idea/ suggestions on how to get this done?
This is a typical example of view controller containment (where you want one view controller to present other view controllers). Navigation controllers and tab bar controllers are example of built in container controllers. But effective iOS 5, Apple opened up containment for the rest of us.
Please see:
Implementing a Container View Controller in the UIViewController Class Reference.
Creating Custom Container View Controllers in the View Controller Programming Guide.
WWDC 2011 - Implementing UIViewController Containment
By the way, buried in the View Controller Programming Guide is subtle note about those four containment methods:
addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:
There are some strange interplay here. I would have thought that we, as application developers, would either just do the add... and/or remove... and that iOS would take care of all of the notifications for us, or that we would have to take care of the will... and did... notifications ourselves. But it's actually half-and-half. So read Adding and Removing a Child very carefully.
I am coming from a Windows Visual Studio (VS) background, so I'm finding the Xcode environment, well, overly complex for lack of a better description.
I'm planning an app which will need 4 views (what I would call windows in VS).
1) The main (starting) view would have a Toolbar at the bottom which opens any of 3 views.
2) View A would have a Nav bar at the top for "Cancel" and "Done" which would return to Main.
3) View B would have a Nav bar at the top for "Back" which would return to Main
4) View C would have no Nav bar but would return to Main using a DoubleTap.
I'm finding it very confusing to piece this together without a straightforward example.
Where can I find some clear explanations of Views vs Controllers, what they're each used for, and how to use them, preferably with examples/tutorials/etc?
Online is best, books are fine.
I'm using Xcode 4.2, no storyboards (for ios 4.2 compatibility).
Thanks.
The general distinction between view controllers and view is something that you can understand independently of Xcode/Cocoa - it's a design pattern called MVC (Model, View, Controller).
In MVC, your application structure is split into 3 layers:
1) The model is your data layer, such as files, databases, network services, and objects that exist independently of the display such as a user.
2) The view is what you see on screen. A view is often composed of several sub views in a hierarchy, for example a window (which is a type of view) contains a toolbar (another type of view) and some buttons (each a view), labels, text fields, etc. These are all views.
3) The controller, aka view controller is the glue that connects these two together. A user object for example has no idea how to display itself, and a label has no knowledge of a user object, so it is the job of the view controller to tell a particular label to display the name of a particular user. Similarly when you type text into a text field, the text field doesn't know that text is a password, so it's the job of the controller to take that text and store it in the correct place, or submit it to the correct web service, or whatever.
So basically a controller converts your model data into the right format to display within your views, and handles feedback from your views (a button press, a text entry, etc) and modifies your model accordingly.
In cocoa every view controller owns a main view (it's "view" property) and may also manage the subviews of that view such as buttons, labels, etc.
Normally there is one view controller class per screen of your app. Occasionally parts of your screen that have standard behaviours are managed by other view controllers.
So for example the navbar is managed by something called a navigation controller. A navigation controller actually manages a stack of view controllers as well as the navigation bar view itself. When you push or pop a view controller onto the navigation controller stack, it makes sure that the view from the current view controller gets displayed and that the navbar shows the correct title. When you tap the back button in the navbar view, the navigation controller receives that button event and pops the current view controller (and it's associated view) off the stack.
The advantage of this approach (MVC) is that is massively cuts down on the amount of subclassing you need to do. Every button on your screen is probably just an instance of a standard UIButton object. You don't need to subclass each button just to change it's behaviour because the button doesn't need to know anything about what happens when it is pressed, it just delegates that press to the view controller to manage.
Generally, you rarely need to create custom view subclasses. Almost all of your application can be built by arranging standard views on a screen and managing them with a custom view controller subclass.
Nibs/xibs are particularly useful for this because they let you visually lay out your views and visually bind their actions (e.g. button taps) to methods on your view controller using drag a drop. This saves you filling up your view controller with pointless layout code (create a button with these coordinates and this colour and attach it to this subview, etc). Unfortunately nibs can be confusing for new developers because they hide a lot of what is going on behind the scenes.
For multi-screen apps, iOS provides a set of so-called container controllers, which are controllers that manage multiple sub-controllers. UITabBarController and UINavigationController are the main examples. UITabBarController is good if you have several screens that you want to tab between, UINavigationController is good if you have a hierarchy of screens that the user can go back and forth between like a browser.
From What I understand based on what I read, most of the time we will be dealing with view when creating apps for the iPhone. Adding sub view to table view, adding table view to a UIView....etc
So my question is how do I go about mix and match all the views? Let say I start off by using a template in Xcode (Tab Bar Application) which basically give me 2 "section", a tab bar controller with 2 UIView to began with. I modified the code for the UIView so that I end up with 2 table view. Now I wanted to an add additional view to the table view whenever I tap on a cell on the table view. I create a new view controller call firstDetailView and hook them up but nothing happen. Surprisingly the app doesn't crash.
I might do it wrongly or have missed something. I am a newbies to programming. Any help would be appreciated.
Thanks.
If you want to deal with different views which are handled by a view controller you should read the View Controller Programming Guide
Navigation through views will be done with a Navigation Controller (Guide here)
Tab bar's are explained as well (Guide here)
Try to read the Apple documentation in the first hand, they are pretty good and all basic stuff is explained there.
I'm tinkering with an iPad app that (like many iPad apps) doesn't use the UINavigation root view control system, so I don't have natural ownership for each app "view". I essentially have two basic views: a document list view, and a document edit view.
I'm playing with UIView animation for getting from a selected document to the edit view.
I also have a toolbar on top that exists (with different buttons) in both "views".
Because I don't have UINavigation running the show for me, I have a tendency to just throw more and more stuff into one NIB and one view controller that owns the whole container. But now I'm trying to figure out how to segue from the document list view to the edit view if the edit view lives inside a different NIB, preserving the toolbar too.
Anyone have thoughts or experience on app structures like this? I find the docs lacking on best practices around code/UI structure for anything except trivial one-screen apps or full-on navigation apps.
You're not "supposed" to have parent/child view controllers owning subcomponents of the same "screen" according to the docs, but this implies one massive honking view controller that basically contains the whole app, and that can't be right.
Not sure if there's a "right answer" to this; I'm looking for some intelligent examples or suggestions. Nobody's touched this question in months, so I'm adding a bounty to generate good chatter. :)
Thanks!
UPDATE: I'm not talking about a split view, which is clearly well handled by a split view controller. Instead, take a look at Apple's iWork apps (e.g. Pages) which have a document list view and an independent edit view, but these are related by animation.
Maybe the real question here is: how would you (or could you even?) build a "container" view controller like the split view or navigation controller, yourself? Are you required to build the whole damn thing from scratch? I sense that you are, because seems to be hidden wiring in the interaction between view controllers. If so, thoughts on this?
I think the only hidden wiring in view controllers is setting parentViewController, which is required to support the categories declared for split and navigation.
View controllers are designed to be nested, with each controller owning a part of the view hierarchy. The only design goal is that no view controller reach into the view hierarchy of another controller. A parent view controller will usually have some call for adding child controllers so that it can set the frame of the view within the view hierarchy it owns. A child view controller should not do anything to the superview of the view it controls, as that is owned by another controller. Not should it set the center or frame of the view it controls.
For example, a navigation controller has a push method, in which it removes the previous controller view, adds the new controller view, and sets the frame of the newly added view. In general, a parent view controller is free to set the frame of the view of a child controller, but not the bounds.
If you want to change the animation of a navigation controller, I think you would start by implementing every method with an animated: argument. Set up your animation then call super with the animated flag off before committing the animation.
I haven't tried the multiple-view-controllers thing outside of the UIKit-provided ones (navigation/tab-bar/modal/etc) but I don't see why it shouldn't work. Under the hood, everything is a view, though I'll note that UIKit has special views for view controllers which no doubt have some kind of special handling by the system (UIViewController has a wrapper view, UINavigationController has a UINavigationTransitionView or something, ...).
I'd advise not worrying too much about "best practice" — just code something which does what you want. A couple of options:
Stick logic into view classes (ewwww!). One of our apps does this so it can handle rotation in a custom way (views slide in/out instead of rotating). We should've probably implemented our own view controller logic instead.
Break the model into components which correspond to views. Make each view know how to load its component and recursively load subcomponents. Then the view controller only needs to worry about "big picture" stuff.
Also note that you can load multiple nibs into the same view controller by e.g. connecting it to an outlet called editView.The big difference is that it's not done automatically by -[UIViewController loadView] so you need to do something like
-(EditView*)editView {
if (!editView) {
// Loads EditView into the outlet editView
[NSBundle loadNibNamed:#"EditView" owner:self];
}
return editView;
}
You'll also need to worry about adding it to your view hierarchy, unloading it on -(void)viewDidUnload (iPhone OS 3.0+), setting it up in -(void)viewDidLoad in case there was a memory warning during editing mode, etc...
It's not easy, but UI never is.
You need a master-detail view implemented with a split-view/popover-view and controlled with a UISplitViewController.
The master view is the document list and the detail view is the edit view. Each has its own controller. The two controllers themselves are managed by the UISplitViewController.
If you don't use the splitview controller you will just end up hand coding something that works very much like it. This is really the only way to do what you want easily in the API and it is the layout that iPad users will expect.
See Creating a Split View Interface in the iPad programming guide for details.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have just started developing iPhone applications and I am very confused by how the "view controller" aspect of the user interface works.
I did the "Your First iPhone Application" tutorial on the Dev Center. It has you set up your own view controller class and then initialize it using initWithNibName. So it seems that nib files contain view controllers. But it's also possible to have a nib file that just has a view, not a view controller. For example if you set up a TabBarController and then navigate to any tab other than the first one, there will be a gray box that says "view" and if you double click that you get to set up a view to go in that tab (but it's just a view, not a view controller, am I right?) So are views subclasses of view controllers or vice versa?
Another thing I am having trouble understanding is nested view controllers. The way I understand that you use a view controller (at least from the tutorial) is that you create your own custom view controller (or is it actually a view controller? In the tutorial I don't see where myViewController is actually declared to extend UIViewController) that has all the delegate methods in it, and then use initWithNibName to load the existing view controller into the custom view controller. (Right so far?) So suppose I create a nib file with a TabBarController at the root, and of course each tab will have a root view controller. So then I loadWithNibName the file and stick it in my own root view controller. Now how do I get access to all the "internal" view controllers so that I can assign delegate methods to them? Or is the recommended option to make the root view controller the delegate for both its own view and the views of all the subsidiary view controllers?
Here's another example. I am planning to have a TabBarController where for some of the tabs, the view controller for that tab will be a NavigationController. The way I understand navigation controllers is that you have to programmatically push a view on top of the stack when you want to drill down in the hierarchy. Suppose the view I pushed on is a view I originally created in Interface Builder (and loaded in using initWithNibName.) But of course the space to display the view is smaller than the space available for the view when I created it (because when I created it it was on a blank slate, while when I display it there's a navigation bar and a tab bar using up some of the screen.) So do the view controllers automatically resize the view to compensate? (IIRC, part of the documentation did mention auto-resizing somehow, but it seems like since the aspect ratio changes, scaling to the right size would leave the text looking "squashed".)
Finally is there some tutorial or explanation somewhere that explains clearly how the view controllers work? That also might help me answer my questions.
Docs on view controllers and learning related stuff
(1) Apple's UIViewController reference. Short and sweet (relatively).
(2) View Controller Programming Guide for iPhone OS. More wordy.
(3) Not view controller specific, but still: Cocoa Dev Central. Education with pretty pictures.
Nested View Controllers
The fact is that there are some key points that are a tad glossed over in the introductory docs. And I think a lot of the confusion arises from using the tab bar controller and navigation controller in particular.
For example:
You should not use view controllers to manage views that fill only a part of their window—that is, only part of the area defined by the application content rectangle. If you want to have an interface composed of several smaller views, embed them all in a single root view and manage that view with your view controller.
-UIViewController class reference
So, that certainly makes it sound like you should never nest view controllers, right? Well, from my experience, what they meant to say was something more like never nest view controllers, except maybe in a tab bar controller, or in a navigation controller, or in a navigation controller in a tab bar controller. But other than that, never nest view controllers.
View resizing
Another good question you raise: Is the coder responsible for sizing the view, or is that done by a view controller? And the usual answer is: yes, the coder is responsible for all layout and exact sizing of view elements -- except when that view is the first one added to a tab bar or navigation controller -- they tend to be somewhat aggressive about sizing your views for you. There are more details to know - things like autoresizing your view if the orientation changes - but this is a good rule of thumb to start with.
Views vs view controllers (and models)
Neither views nor view controllers are subclasses of each other. They're independent dudes. Generally, a view controller is more in charge, and tells the view what data to display, or where to position itself, etc. Views don't really tell controllers what do to, except perhaps to inform them of a user action, such as a UIButton calling a method in its controller when it gets pushed.
Here's a quick analogy to help understand the whole MVC model. Imagine you're building the UI for a car. You need to build a dashboard to display information to the driver - this is the view. You need sensors to know how fast it's going, how much gas you have, and what radio station is on - this data and direct data-handling stuff are like model objects. Finally, you need a system which knows when to turn on the low-on-gas light, or to turn off your turn signal when you turn the wheel far enough, and all the logic like that - this is the controller component.
Other stuff
A nib file is mostly a way to save view-related data that would make for ugly code. You can think of them logically as freeze-dried class instances, ready to use. For example, positioning a grid of 20 buttons that will be the UI for a calculator; a bunch of pixel coordinates makes for boring code, and is a lot easier to work with in interface builder. It can also accommodate view controllers because that code is also occasionally very boilerplate - such as when you need a standard, everyday tab bar controller.
About which view controllers control which views: Again, the tab bar and navigation controllers are kind of special cases, as they can act as containers for other view controllers. By default, you think of having just one view controller in charge of the full screen at a time, and in that case, there's no question that this one view controller is handling any delegated calls back from your view or other elements. If you do have some container view controllers, then it still makes sense for the most-specific view controller (the most nested one) to be doing all the dirty work, at least for the views which are not controlled by the container controllers (i.e. anything not the tab bar / navigation bar). This is because the container view controllers aren't usually considered as knowing about what they contain, and this agnosticism gives us better decoupled, and more maintainable code.
And, yes, in this context a view controller is always meant to be a subclass of UIViewController.
View controllers are simply that - objects that handle control of a view.
A XIB files doesn't "contain" a view controller. Instead it normally tells a XIB, what view controller it will be wired up to eventually - that's what the initWithNib call is doing, creating a view controller, getting the view out of the xib, and then attaching the view controller to where the XIB says it should connect to parts of the view.
There are nested view controllers technically when you use a navigation controller or tab bar, but your own view controller basically gets called as if it were the top level because those containers understand they will be holding other view controllers.
As for resizing - it's not a pixel resize, it's a container resize. The view controller resizes the master view it's hooked up to, then the auto-resizing behavior for any elements that view holds determines how they are resized - some things like lables might shift around, but by default do not shrink. If you click on the Ruler tab in IB you can see the current autoresize behavior for any object in a view - the center lines with arrows at both ends tell you if an object will allow resizing, and in which directions. The lines on the outside of the square tell you what side(s) the object will "stick" to, meaning the object will keep the same distance from those edges no matter how the container holding it resizes.
I'm not sure what the best book for IB is, but you probably cannot go wrong with a good fundamental Cocoa book which should explain autoresize behaviors.