Adding a View Controller as a Subview in Another View Controller

Adding a view controller as a subview in another view controller

A couple of observations:

  1. When you instantiate the second view controller, you are calling ViewControllerB(). If that view controller programmatically creates its view (which is unusual) that would be fine. But the presence of the IBOutlet suggests that this second view controller's scene was defined in Interface Builder, but by calling ViewControllerB(), you are not giving the storyboard a chance to instantiate that scene and hook up all the outlets. Thus the implicitly unwrapped UILabel is nil, resulting in your error message.

    Instead, you want to give your destination view controller a "storyboard id" in Interface Builder and then you can use instantiateViewController(withIdentifier:) to instantiate it (and hook up all of the IB outlets). In Swift 3:

    let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")

    You can now access this controller's view.

  2. But if you really want to do addSubview (i.e. you're not transitioning to the next scene), then you are engaging in a practice called "view controller containment". You do not just want to simply addSubview. You want to do some additional container view controller calls, e.g.:

    let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
    addChild(controller)
    controller.view.frame = ... // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
    view.addSubview(controller.view)
    controller.didMove(toParent: self)

    For more information about why this addChild (previously called addChildViewController) and didMove(toParent:) (previously called didMove(toParentViewController:)) are necessary, see WWDC 2011 video #102 - Implementing UIViewController Containment. In short, you need to ensure that your view controller hierarchy stays in sync with your view hierarchy, and these calls to addChild and didMove(toParent:) ensure this is the case.

    Also see Creating Custom Container View Controllers in the View Controller Programming Guide.


By the way, the above illustrates how to do this programmatically. It is actually much easier if you use the "container view" in Interface Builder.

Sample Image

Then you don't have to worry about any of these containment-related calls, and Interface Builder will take care of it for you.

For Swift 2 implementation, see previous revision of this answer.

Adding new Viewcontroller's view as subview

You need to also add CustomViewController as ChildViewController in your current Controller.

let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "customView") as! CustomViewController
vc.view.frame = self.view.bounds
self.addChildViewController(vc)
self.view.addSubview(vc.view)
vc.didMove(toParentViewController: self) //OR vc.willMove(toParentViewController: self)

Add a view controller as a subview in another view controller

Somehow i am able to fix your issue with below changes:

Replace this method carbonTabSwipeNavigation.insert(intoRootViewController: self) with carbonTabSwipeNavigation.insert(intoRootViewController: self, andTargetView: containerView) in viewDidLoad

Note : Give UITaBar bottom constraint to SuperView not SafeArea:

Sample Image

Add below code in ViewController:

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

tabbar.invalidateIntrinsicContentSize()
}

After doing this when you run you will UITabBar:

Sample Image

Adding An UITableViewController on to a SubView

So just to answer this question, indeed you got two options. One is the best way, as suggested by Rakesha. Just use UITableView. Add it as a subview. Done.

And in the future, if you really want any controller to be added onto any UIView, remember you need to add that controller as a child. For example, in your case:

The controller of the view that will hold your UITableViewController will add such UITableViewController as a child.

self.addChild(yourUITableViewController)
self.whatEverViewContainer.addSubview(yourUITableViewController.view)
// Take note of the view of your tableViewController above^.
// Then setup the constraints of your yourUITableViewController.view below.

I hope this helps!

add UIViewController in subview

You should use Child containment concept, here MainViewController is a parent view controller and you want to add child view controller view as a subview on Main View Controller.

Adding and Removing a Child

//call displayContentController to add SampleViewCOntroller view to mainViewcontroller
[self displayContentController:sampleVCObject];

// write this method in MainViewController
- (void) displayContentController: (UIViewController*) content;
{
[self addChildViewController:content]; // 1
content.view.bounds = testView.bounds; //2
[testView addSubview:content.view];
[content didMoveToParentViewController:self]; // 3
}

Here’s what the code does:

It calls the container’s addChildViewController: method to add the child. Calling the addChildViewController: method also calls the child’s willMoveToParentViewController: method automatically.
It accesses the child’s view property to retrieve the view and adds it to its own view hierarchy. The container sets the child’s size and position before adding the view; containers always choose where the child’s content appears. Although this example does this by explicitly setting the frame, you could also use layout constraints to determine the view’s position.
It explicitly calls the child’s didMoveToParentViewController: method to signal that the operation is complete.

//you can also write this method in MainViewController to remove the child VC you added before.
- (void) hideContentController: (UIViewController*) content
{
[content willMoveToParentViewController:nil]; // 1
[content.view removeFromSuperview]; // 2
[content removeFromParentViewController]; // 3
}

For more details, please refer to apple doc:
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

Configuring a Container in Interface Builder, for those who don't want to write code.

To create a parent-child container relationship at design time, add a container view object to your storyboard scene, as shown in Figure 5-3. A container view object is a placeholder object that represents the contents of a child view controller. Use that view to size and position the child’s root view in relation to the other views in the container.

Adding a container view in Interface Builder
When you load a view controller with one or more container views, Interface Builder also loads the child view controllers associated with those views. The children must be instantiated at the same time as the parent so that the appropriate parent-child relationships can be created.

Add TableViewController as SubView

All you are currently doing is getting the view from the other controllers. You need to create an instance of the view controllers and keep them in memory.

This can be done by adding them as child view controllers:

    // for both inbox and outbox table view controllers,
// instantiate
// add as child view controller
// add its view as a subview of container
// finish with .didMove()

inboxTVC = InboxTableViewController()
addChild(inboxTVC)
container.addSubview(inboxTVC.view)
inboxTVC.didMove(toParent: self)

outboxTVC = OutboxTableViewController()
addChild(outboxTVC)
container.addSubview(outboxTVC.view)
outboxTVC.didMove(toParent: self)

I've updated the project I put together for your other question with this implemented: https://github.com/DonMag/AliAdil

Adding subviews programmatically in presented view controller

Value of containerView.frame inside viewDidLoad is inaccurate Implement

var chart_axes:ChartAxes!

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
chart_axes.frame = containerView.frame
}

OR set constraints in place

let chart_axes = ChartAxes(frame: containerView.frame)
chart_axes.backgroundColor = UIColor.red.withAlphaComponent(0.6)
containerView.addSubview(chart_axes)
chart_axes.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
chart_axes.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
chart_axes.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
chart_axes.topAnchor.constraint(equalTo: containerView.topAnchor),
chart_axes.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
])


Related Topics



Leave a reply



Submit