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.
CodePudding user response:
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)
])
}
}
