I am trying to create a very simple stackView in my viewcontroller. I want the stackView to cover the entire screen. How I am creating the stackView is
import UIKit
import Firebase
class Vc: UIViewController {
var scrollView: UIScrollView {
let scroll = UIScrollView()
scroll.isScrollEnabled = true
return scroll
}
var stackView: UIStackView {
let stack = UIStackView()
stack.axis = .vertical
stack.distribution = .fillEqually
return stack
}
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.tintColor = .white
self.navigationItem.title = "Profile"
self.view.backgroundColor = UIColor.white
addStackViewAnchors()
}
func addStackViewAnchors() {
view.addSubview(stackView)
stackView.anchors(top: view.safeAreaLayoutGuide.topAnchor, topPad: 0, bottom: view.safeAreaLayoutGuide.bottomAnchor, bottomPad: 0, left: view.safeAreaLayoutGuide.leftAnchor, leftPad: 0, right: view.safeAreaLayoutGuide.rightAnchor, rightPad: 0, height: .zero, width: .zero)
}
}
When I run this, my app crashes and it says
Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x283c5e840 "UIStackView:0x135666a90.top"> and <NSLayoutYAxisAnchor:0x283c5e140 "UILayoutGuide:0x28103b8e0'UIViewSafeAreaLayoutGuide'.top"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
terminating with uncaught exception of type NSException
There are no conflicting constraints because the stackView is the only anchor being set.
Every time you called stackView
here you init
a new instance of Stack View from inside your function. That's the reason when you called stackView.anchor
the error appears because it is autolayout the new instance of stackView
not the stackView
you add subview into your VC
.
The thing you should do is create a variable to store your stackView
instance so the stackView
init for once and reuse in all in the VC
.
Beside of that, we use leadingAnchor
instead of leftAnchor
; trailingAnchor
instead of rightAnchor
.
Code will be like this
class ViewController: UIViewController {
private var stackViewInScreen : UIStackView?
var stackView: UIStackView {
let stack = UIStackView()
stack.axis = .vertical
stack.distribution = .fillEqually
return stack
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
addStackViewAnchors()
}
func addStackViewAnchors() {
self.stackViewInScreen = stackView
self.view.addSubview(self.stackViewInScreen!)
self.stackViewInScreen!.translatesAutoresizingMaskIntoConstraints = false
self.stackViewInScreen?.backgroundColor = UIColor.orange
NSLayoutConstraint.activate([
self.stackViewInScreen!.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0),
self.stackViewInScreen!.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0),
self.stackViewInScreen!.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0),
self.stackViewInScreen!.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
])
}
}