I have a UIScrollView in my app and I am adding some custom views from xib to it so you can horizontally scroll (tabbing) in ScrollView to change which one is shown. For now this works but I have a problem with connecting views to controllers.
I don't know how to choose structure of ViewControllers (how many controllers should I use, use nested controllers,...).
I have a rootView and its controller. In this rootView there is a ScrollView and this ScrollView contains some custom views (subviews) loaded from xib (using loadNibNamed method).
My question is should I use the same ViewController as for rootView also for these subviews in ScrollView? Problem is that the ViewControllers view property is already bind to the rootView (super view in rootView) so when I bind this view property also to subviews an error is occurred. Also if I create new controller for these subviews an error is occurred as well.
When I am loading subviews to the ScrollView with loadNibNamed method in ViewController of rootView, owner of these subviews is ViewController (owner argument of loadNibNamed method is set to self).
Can you tell me please, how should I solve this? What controller should I use for subviews, should I create new one or should I use existing one. Or should I use some nested controller? I am newbie in iOS development so I have a chaos in using ViewControllers right now...
If there isn't much code that is relative to controlling the sub views you could use just the root view controller. i.e A single controller for a single scene would be a good MVC approach.
If you are using it this way , don't change the view property of view controller as this messes it up for the root view - controller setup. If you just need a reference to this views you already have it with the return value of loadNibNamed. Also if you are setting the owner to self then create additional instance variable to hold the sub views(and not the view property) so that you can specify the owner from the xib itself and connect the references appropriately.
However if you have substantial business logic to be written regarding the sub views then its fine to create separate view-controllers(a single class would be fine if all the subviews behave the more or less same way if you are getting what i mean) for it. In the xib for the subviews, you can specify this class as the owner and when using loadNibNamed: you should create an object of the subviewcontroller class and specify this as the owner. This way you can modularize the whole thing.
Related
Can any one explain when should we add a UIViewController as ChildViewController?
What is the benefits of adding it as ChildViewController instead of subView?
Please help me to understand the purpose of ChildViewController.
When you add a view controller as child view controller, the parent view controller will hold a strong pointer to the child view controller so it doesn't get released instantly. This does not automatically add child's view to parent's view. So you will have to call them both.
I only used it when I needed to create multiple view controllers to be inserted in another view controller and didn't need to directly access it.
its all about UI and code management if you are using subview to achieve what you want to implement inside your app you need to code for your view inside same viewcontrollers class but something interesting i found by creating childviewcontrollers.
empowered to work on a seprate viewcontroller will invoked along with its parent viewcontroller along with its seprate class.
infinite controllers that will be updated tapping a button.
Creation of childViewControllers can be achived by implementing containerView.
or you must have a look of this link hope its helpful to understand.
Lets say I have a container view in a parent UIView.
What is the difference between referencing it as an Outlet in my parent UIView, or accessing it this way :
categoryContainerViewController = self.childViewControllers[0] as! CategoriesControllerView
View and view controllers are two different things
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.
now you can get idea about View and a view controller.
A view and a view controller are two totally different things.
categoryContainerViewController = self.childViewControllers[0] as! CategoriesControllerView
In spite of the name, that is a view controller.
The outlet is to the view.
In layman terms : -
IBOutlet connects any view element from your interface builder to attached swift class file. So you can get reference to any subview of UIView(eg, UILabel, UIButton) from interface builder to your UIViewController or UIView Swift class
In your ex.
by using
categoryContainerViewController = self.childViewControllers[0] as! CategoriesControllerView
You are getting reference to your ChildViewController and not any view
I know there is the common practice in iOS development of having one UIViewController presented on the screen whose view is loaded from a XIB which will contain all the UIView subclasses in it.
While I was working on a pretty complex widget for an app, I decided to make the widget subclass a UIViewController instead of a UIView. This was because I thought a UIViewController was essentially a UIView with some helper methods around it. Then I could create a XIB for it (I know UIViews can have their own XIBs too), load the views it contains, place ITS view in the presented parent VC's view, and lay it out.
This works fine so far, but I'm wondering if this is bad practice and if I should just subclass a UIView instead and give it a normal NSObject controller. I am seeing some problems with this and I was wondering if anybody could address concerns I have with this approach?
EDIT NOTE: The widget VC does NOT relate to the VC view it is in and is reusable on ANY screen. So the answer is not subclassing the widget VC with the parent VC. The widget is INSIDE the parent VC, but it is NOT a parent VC.
EDIT NOTE 2: I am NOT using Storyboard. Only Autolayout, XIBs, and ARC.
Why can't we have VC's in VC's?
1) Can VC's be simply dropped into ANOTHER VC's XIB and be loaded easily as a subview?
2) I read here: When to use a UIView vs. a UIViewController on the iPhone?
The top answer explains how the VC controls rotation of the screen and laying out the subviews again, so if you add another VC, then the system will automatically think that THAT is the main VC and will attempt to rotate it instead, causing problems. Is this true? Or is he just talking about if you somehow got into a state where 2 VC's were "presented"? I wasn't sure if his answer applied to VC views that were SUBVIEWS of other VC views.
3) In general is this good practice? It certainly seemed more reasonable as it made loading the subview VC's view much easier.
Thanks!
It's absolutely fine. The answer to your problem is ContainerView.
Container View defines a region within a view controller's view subgraph that can include a child view controller. Create an embed segue from the container view to the child view controller in the storyboard.
You almost got it right. Yes, it's good to make a view controller for what you needed. But you shouldn't just add it's view to the parent view, you should also add the view controller as a child view controller of the first view.
You can add many views controllers as child view controllers of a view controller.
You can learn more about this here.
How should I go about creating a View for the storyboard programmatically? I want to access the labels from the first ViewController object made(automatically to call the IBAction methods of VC). I know that this first object of VC is the one linked to the view in the storyboard(?) and I need to change a label form another file, besides VC. I'm pretty sure the only way to do so would be to access the VC object that is linked to the view, or create one and not go with the default one that is created. If not, how would I go about accessing the labels of the view from another file?
You don't create storyboard objects programmatically. A storyboard is very basically an XML file Xcode uses to call different view controllers. The biggest advantage of using storyboards over NIBs is you can layout transitions or segues, and the advantage of NIBs or storyboards over initiating view controllers by code is obviously the visual interface. So your question doesn't really make sense.
If you want to reference a particular view controller's label from your storyboard you need to create a pointer to that view controller first, but changing it programmatically doesn't make sense because that's what storyboard is for.
That said you may just need to go look for your class name in your view controller's Identity Inspector in storyboard and then edit your label programmatically through an IBOutlet property.
I cannot find where the view and viewcontroller get hooked? Is it in the xib file?
I learned that each viewcontroller can control several views, but where are those two get hooked?
I recommend you to read the whole ViewController Programming Guide if you have doubts like that:
ViewController Programming Guide
In case you want to jump right to your issue, check this section:
Resource Managment in ViewControllers
You can find a nice graph explaining where the views are created and linked in the ViewController:
A ViewController is just that, a class to manage the UIViews (there will be many) that it contains. The main view is automatically wired up for you and you are responsible for wiring up all the other views you add. Keep in mind that UIButtons, UILabels, UIViews, etc are all objects that inherit from UIView.
Like Antonio indicated, start with the Apple docs:
The view controller has its own view. Each child view (subview) view has a parent view (superview). You can nest views inside of views. In your case, the top view in the hierarchy is the view controller's view.
At design time, you can add a child view to any view in Interface Builder by simply dragging a new view onto the parent view. You can also adjust the view hierarchy from the Document Outline in Interface Builder.
When creating a view hierarchy in Interface Builder, the view hierarchy is stored in the .xib file.
At run time, your views are instantiated from the information in the .xib file, and each child view's superview property points to its parent view. Each view also has a subviews property that lists each of its child views.
You can add a view to any other view at run time by instantiating a new view and passing it to the parent view's addSubview method. Obviously, once instantiated, you can alter the view hierarchy by setting the superview and subviews properties and calling related methods.