Adding a view controller as a subview in another view controller
A couple of observations:
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 theIBOutlet
suggests that this second view controller's scene was defined in Interface Builder, but by callingViewControllerB()
, you are not giving the storyboard a chance to instantiate that scene and hook up all the outlets. Thus the implicitly unwrappedUILabel
isnil
, 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
'sview
.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 simplyaddSubview
. 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 calledaddChildViewController
) anddidMove(toParent:)
(previously calleddidMove(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 toaddChild
anddidMove(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.
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:
Add below code in ViewController:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tabbar.invalidateIntrinsicContentSize()
}
After doing this when you run you will UITabBar
:
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.
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
How to Disable Copy Paste Option from Uitextfield Programmatically
Detecting Color of Iphone/Ipad/Ipod Touch
Run Code Only After Asynchronous Function Finishes Executing
What Are the Dangers of Method Swizzling in Objective-C
How to Write Dispatch_After Gcd in Swift 3, 4, and 5
Detect Current Device With Ui_User_Interface_Idiom() in Swift
Ios: Multi-Line Uilabel in Auto Layout
Change Default Scrolling Behavior of Uitableview Section Header
Basic Example For Sharing Text or Image With Uiactivityviewcontroller in Swift
Transparent iOS Navigation Bar
Make a Phone Call Programmatically
Uilabel - Auto-Size Label to Fit Text
Adding a View Controller as a Subview in Another View Controller
How to Programmatically Check Whether a Keyboard Is Present in iOS App
How to Get the Color of a Pixel in a Uiimage With Swift