Should I embed a view controller's view within a new view? - ios

When adding an external view controller to an existing one in the Storyboard you would use a "container view". When adding one programatically you are presented with the option of creating a new UIView to embed the external VC's view within (replicating a container view) or simply just adding the external VC's .view directly into the existing one.
Which is considered the better practise here when doing this programatically? Does one have a different effect than the other on performance or reliability?

Using a container view in Storyboard automates the process of:
instantiate view controller
add as childViewController
add its view as a subview of the container view (which is a subview of the main view)
Adding a child view controller via code is the same process:
instantiate view controller
add as childViewController
add its view as a subview of the current view, or as a subview of another subview of the current view
The other benefit of using a container view in Storyboard is that you get a visual design interface.
Of course, some people don't like Storyboard / IB, and prefer code-only approaches.
So really, whichever method best suits your needs and development style.

Related

IOS: One navigation view controller with many different views - how should I do it?

I'm trying to create an IOS app that has one navigation view controller with several bar buttons, where each button changes the content of the view itself. Most of my views are custom views anyway, so I won't really see any clear previews in the storyboard anyway.
I'm thinking about creating one navigation view controller, and several NIB files to represent each view. Each NIB will have its own class with all the IBOutlets and IBActions.
Then, when a button is clicked in the navigation view controller, just switch to a new view by clearing the old one (removeFromSuperview), and call loadNibNamed to load a new view.
Does this sound reasonable or will all this deserializing be expensive in terms of CPU? Would it be better to just create different viewcontrollers in the storyboard, with segues etc, and copy those nav bar buttons to each view controller?
The simplest solution:
ViewController->
View->
rootViewOne
rootViewTwo
rootViewThree
...
upon your bar button's action,set specific rootView's hidden property to true or false:
self.rootViewOne.hidden = currentIndex == 0
self.rootViewTwo.hidden = currentIndex == 1
self.rootViewThree.hidden = currentIndex == 2
You can add your other view controller/s as child view controller.
In this way, you will have code for different views in their respective view controllers and your main/parent view controller will not be messy.
To add child view controller:
// Get instance of your view controller
UIViewController *childViewController = [UIViewController new];
// Add your view controller as a child view controller
[self addChildViewController:self.loginView];
// Set frame for your childViewController's view
[childViewController.view setFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.view.frame.size.height)];
// Add childViewController's view as a subview to your viewcontroller's view
[self.view addSubview:childViewController.view];
// Notify your main/parent controller that a child view controller is being added
[childViewController didMoveToParentViewController:self];
To remove child view controller:
// Notify the childViewController that it will be removed
[childViewController willMoveToParentViewController:nil];
// Remove childViewController's view
[childViewController.view removeFromSuperview];
// Remove childViewController from your main/parent view controller
[childViewController removeFromParentViewController];
Hope this helps.
UPDATE - Embedded swapping by Sandmoose Software:
http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers
Here's a snippet from the "how-it-works" section:
The segue between ViewController and ContainerViewController is an
embed segue. The segues between ContainerViewController and its two
child view controllers is a custom segue. This custom segue is named
Empty and is a subclass of UIStoryboardSegue. It contains an empty
perform method. The ContainerViewController will take care of moving
the child view controllers into and out of place. However, the fake
segues are needed to create the connections in the storyboard.
If you’re like me you cringe at the thought of having a fake/empty
class like this but the benefit is that it allows us to stay firmly in
the world of storyboard idioms without resorting to programmatically
loading isolated storyboard scenes. It’s one tiny bit of ugliness
which allows us to preserve the usefulness and elegance of
storyboards. The storyboard still visually represents the scenes and
their relationships accurately. We can still use segues to control
what happens.
---------- Old answer below (phfffft!) ------
You pose several different questions here: one regarding custom buttons in the nav bar of a nav controller, another about assigning multiple views to the nav controller, and one about placing the view in separate XIB files, while maintaining IBOutlet connections and such.
The first one calls for a tab bar controller, which you can customize to look in whatever way you deem fit, even like a nav bar (ADC has ready-to-use sample code, "UIKit Catalog (iOS): Creating and Customizing UIKit Controls", which fits your needs).
The second can be done easily in Interface Builder by following any number of instructions freely available on YouTube, at Apple, and elsewhere on the Internet; you'll find it an extremely intuitive process. If you can drag-connect a tab bar controller to a view controller, you can intuit the rest. Otherwise, Apple has sample code for customizing the navigation or transition between views in a single view controller interface. "State Restoration of Child View Controllers" provides the best structure for what you want (just pull out the restoration-related code, and use the rest).
The third is not intuitive at all; and, as far as I know, there are only a couple of sets of instructions that exist for separating views (or other view controllers and their views) from a parent or top-level view controller. Here's one I haven't tried yet, so I'll be interested to hear how it worked for you:
http://digginginswift.com/2015/08/30/making-reusable-views-in-separate-xibs
The technique I use involves creating a storyboard with a single view controller to start, followed by a new view controller embedded in a container view for each of your intended views; then, deleting the view in each of the child view controllers, which leaves place for the views you set up in separate XIBs. They are connected by setting the File's Owner to the parent view controller. I can send you sample code, if you'd like to try a different approach than the aforementioned website offers.

Getting a VC to appear inside another VC

I have 2 ViewControllers.
VC1 has a 2 views inside it.
I want to get MenuUIVC to appear in one of my views belonging(child) to VC1.
I tried this code inside of VC1 but it didn't work.
MenuUIVC * menuViewVC = [[MenuUIVC alloc] init];
menuUIView = menuViewVC.view;
I expected to be able to see the MenuUIVC inside the view (menuUIView) which is a child of VC1. I have the IBOutlets all hooked up on the storyboard.
You can use Container views to get View Controller inside a View Controller. And, you can get the reference to it through prepareForSegue() method.
Links for description:
iOS Container View
The Easy Way to Switch Container Views in iOS
If you are using UIView, then why don't you use
[menuUIView addSubview:menuViewVC.view];
Another option is to use childviewcontrollers.
See these links for example:-
adding view controller as child view in ios
Add child view controller to current view controller
Using container or child view controller, gives you full fledge option of using View Controller properties, which you will not get in UIView.
Say for example, you can you orientation delegate methods, which you can't using in UIView class directly.
Hope this can help you.
Cheers
Sanjay
you can go for container view if you want to do it using IBOutlets & storyborad.
but if you want to do it using code then follow the below steps :
initialise & create parent view controller.
then add required child view as a subview with negative frame.
now change the frame with UIView animation whenever required. & do add tap gesture recogniser on part of screen other than the child view to remove it back to the initial position.

Storyboard - how to make multiple containers embed to the same view controller?

Is there a way for multiple container view's on different scenes to point to one same scene or view controller ? The way I see it, every container has its own embedded scene. What would be the strategy here ? To use the same class on each embedded scene ?
You can hook up multiple container views to the "same" embedded view controller. Control-drag from each container view to the view controller and, when the popup menu appears, choose “embed”.
However, I put "same" in quotes because you need to understand what's going on. At runtime, each container view will create a new instance of the embedded view controller, created by deserializing that part of the storyboard once for each container view. They won't all share the same instance. If you want to keep one persistent view controller that you move around from container to container, you need to do that yourself in code.
Yes, just ctrl-drag from the container to the content view controller and select "embed" You'll also probably want to delete the unreachable view controllers from the storyboard.

In iOS, using storyboard, how to setup a view controller inside a container view?

I have created and drawn out a custom UIViewController called AutocompleteVC in my Main storyboard. AutocompleteVC will be used in several different places/storyboards and with different dimensions.
For example, in my Transit storyboard, shown below,, there is a custom UIViewController called TransitVC, shown on the left. In TransitVC, I have a container view with an IBOutlet called autocompleteContainerView. autocompleteContainerView has a segue called autocompleteEmbedSegue to a generic UIViewController, shown on the right in red.
The goal is to have TransitVC hold AutocompleteVC inside autocompleteContainerView. But I'm having trouble getting this to work. The reason I want to do this inside a container view is so I can use autolayout to set constraints on it. Otherwise, I know how to do this purely in code.
I believe my approach might be flawed. What is the correct approach to do this if I want to maximize storyboard usage.
I'm not sure what you are asking. Setting up a parent/child relationship with a container view is very easy, exactly as you have outlined. Just create a container view inside the parent view controller, create the child view controller scene, and then control-drag from the container view to the child view controller to create the embed segue.

How the view and viewcontroller hooked?

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.

Resources