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.
Related
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.
In an iPad application I have a tab Controller containing several view controllers. One of these view Controller (call it MainViewController) needs 2 table views side by side.
So I wrote 2 UITableViewController subclasses and from MainViewController, I alloc/init both subclasses of UITableViewController, and add the tableview from each to the MainViewController's view.
This means that UITableViewController subclasses's views are subviews of MainViewController's view.
This answer: https://stackoverflow.com/a/7684648/191463 says that doing that is incorrect and it seems Apple are starting to cut down on it.
I really do not want to have to put all the code from both UITableViewControllers in MainViewController, as it will make it much harder to read and in future could create duplicate code, if I want to use one of the tableview elsewhere in the app by itself.
Is this actually a problem, if it is how do I do it properly?
Apple isn't cutting down on it. This is the only way to create custom container view controllers prior to iOS 5. Apple actually listened to the developers and made it easier to do this sort of thing in iOS 5 with child and parent view controller methods, not to mention they made it so it worked hierarchically.
In most cases, this wouldn't actually be a problem in terms of applications crashing or performance or anything. It can be a problem in some cases, because let's say you have a child view controller. You add the view controller's view to your root view controller. Prior to iOS 5, child view controllers were things like navigation controller view controllers, tab bar controller view controllers, and modal view controllers. What happens when you have a button that calls [self.parentViewController dismissModalViewControllerAnimated:YES];? Technically, the view controller isn't being presented as a modal view controller, you added the view to the root view controller view.
In iOS5, you're able to add child view controllers to view controllers and are able to transition from one child view controller to another.
Now even if your view controller doesn't have a different parent, adding a "root" view controller to another root view controller isn't the best way to do it (especially since you don't get access to the parent view controller unless you explicitly create a parentViewController pointer in the child view controller). So in the end, Apple just made it easier and more decoupled.
It is OK to do it so long you take the responsibility of managing the viewController life cycle events
initWithNibName...
loadView:
viewDidLoad:...
.
.
viewDidUnload..
dealloc
memoryWarnings
orientation changes
So if you create a custom "container view controller" it becomes your responsibility to call all these methods on child viewControllers at the appropriate time. Think of it as "If you were to implement UITabBarController" what all will you have to manage regarding the children ??"
It quickly gets complex. Adding another viewController's view as subview is childs play.
iOS 5 does some of this stuff for you by specifying parent child relationship, however I still haven't seen any sample code anywhere yet to point to.
I'd say it is not incorrect or wrong to create view controller containers, especially when Apple engineers do that themselves. UITabBarController, UINavigationController or UISplitViewController - they are all view controller containers. More over many great apps with unique UX do that more common than you think. However the real issue is that it's quite hard to do it the right way, so e.g. view lifecycle, memory management and rotation handling is done properly along the hierarchy of views. Fortunately Apple guys did a decent job and iOS5 introduced lots of functionalities regarding controller containers:
UIViewController class reference
View Controller Programming Guide for iOS
If you're interested how above problems had to be addressed before iOS5, read these two very good blog posts:
Writing high-quality view controller containers
Using view controllers wisely
I have the following structure in my app, is this a correct/valid way of doing it?
UINavigationController attached to the window, the rootcontroller in this navigationcontroller is a UIViewController that presents a tableview. When a user taps one of the rows a UITabBarController is pushed on the stack.
This works, however I began to be unsure when I read this:
Because the UITabBarController class
inherits from the UIViewController
class, tab bar controllers have their
own view that is accessible through
the view property. When deploying a
tab bar interface, you must install
this view as the root of your window.
Unlike other view controllers, a tab
bar interface should never be
installed as a child of another view
controller.
This is not recommended, but it should be OK. The aweful Wordpress app also does this. This depends on the design of your app.
I'm not shure about Apple's approval.
The reason why this is not recommended (and thus might not get approved - now or at a later point!) is user confusion.
Users are used to regard the tab bar as top-level navigation. So if dig down using the table and navigation, and then getting a UITabBar, this is horrible for navigation as the user doesn't know what to expect.
The solution here, of course depending on the use case, is a "switch" in the navigation bar or a toolbar. UISegmentedControl would be a natural choice.
I'm developing an iPhone application and I'm trying to do this:
I want an application with tree views. The view shown first, doesn't have a navigation bar. If the user tap on a button, I need to open the second view with a navigation bar and a table view. The user can also add new items to the table view. If the user do so, the application will show the third view where the user can add fields (this view has also a navigation bar).
It may seem simple, but for me it is not. I don't know how to use the UINavigationController and have not found yet a similar example for what I do (paragraph translated by google).
UPDATE
I don't know how where to put UINavigationController.
How can I do that? Can I use a UIViewController to call a UINavigationController?
Thank you.
take a look at the Recipes example (it also uses core data which may confuse things a little) http://developer.apple.com/iphone/library/samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008913
There is also a simpler starting point here http://developer.apple.com/iphone/library/samplecode/TableViewSuite/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007318 but the Recipe example covers just about everything you need.
EDIT:added the following
For the very simplest example use XCode to build a new application - a navigation based application (sorry, I'm in front of a PC today so that is from memory). That will give you a blank application with the navigation controller created. You then use the navigation controller to push and pop your view controllers
ViewController Programming Guide
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.