使用 swift 的代码约束 - 无法激活
Constraints in code using swift - unable to activate
我正在尝试了解 自动布局约束。在 Ray W 教程挑战(没有解决方案或讨论)之后,布局应如下所示:
在 IB 中做这件事很简单——创建一个黄色视图,具有宽度和高度,垂直居中,水平固定到边缘;然后在该视图中创建带有简单约束的标签、字段和按钮。
我的第一个问题是:如果标签具有固有的内容大小,而其他所有内容都固定在黄色视图中,那么为什么我需要定义固定的宽度和高度?为什么它不从其子视图的固有内容中推断出宽度和高度?
继续尝试在代码中重新创建此布局给我一个错误:
Terminating app due to uncaught exception 'NSGenericException',
reason: 'Unable to activate constraint with items <UILabel:
0x7a961d60; frame = (0 0; 0 0); text = 'Password:';
userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7a961e40>>
and
<UIView: 0x7a96b6f0; frame = (0 0; 0 0); layer = <CALayer:
0x7a96b880>>
because they have no common ancestor. Does the
constraint reference items in different view hierarchies? That's
illegal.'
第二个问题:这些层是什么,我所有的视图都在 heirachy - superview 包含黄色视图包含文本标签和字段。
在经历了很多痛苦之后,我试图准确地重新创建在 IB 中所做的约束,但这只会增加以下错误:
无法同时满足约束条件。
(
"<NSLayoutConstraint:0x7ac57370 H:[UIView:0x7a96b6f0(0)]>",
"<NSLayoutConstraint:0x7ac57400 H:|-(8)-[UILabel:0x7a96bb50'Username:'] (Names: '|':UIView:0x7a96b6f0 )>",
"<NSLayoutConstraint:0x7ac57430 UILabel:0x7a96bb50'Username:'.trailing == UITextField:0x7a961020.leading + 8>",
"<NSLayoutConstraint:0x7ac57520 UITextField:0x7a961020.trailing == UIView:0x7a96b6f0.trailing - 8>" )
最后一个问题:我怎么知道视图 0x7aetc 是什么视图?我的代码中的这个约束在哪里?其他看起来还好(?).
我一定是在一些基本层面上做错了。
这是我的代码:
import UIKit
class ViewController: UIViewController {
let centerView = UIView()
let usernameLabel = UILabel()
let passwordLabel = UILabel()
let usernameField = UITextField()
let passwordField = UITextField()
let submitButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
centerView.backgroundColor = UIColor.yellowColor()
usernameLabel.text = "Username:"
passwordLabel.text = "Password:"
usernameField.borderStyle = .RoundedRect
passwordField.borderStyle = .RoundedRect
submitButton.setTitle("Submit!", forState: .Normal)
submitButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
submitButton.setTitleColor(UIColor.blueColor(), forState: .Highlighted)
view.addSubview(centerView)
self.centerView.addSubview(usernameField)
self.centerView.addSubview(passwordField)
self.centerView.addSubview(usernameLabel)
self.centerView.addSubview(submitButton)
let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
let constraintCenterViewCenterX = NSLayoutConstraint(item: centerView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: 0)
let constraintCenterViewCenterY = NSLayoutConstraint(item: centerView, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1.0, constant: 0)
let constraintUsernameLabelHLeading = NSLayoutConstraint(item: usernameLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel, attribute: .Trailing, relatedBy: .Equal, toItem: usernameField, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintUsernameLabelAlignBottom = NSLayoutConstraint(item: usernameLabel, attribute: .Bottom, relatedBy: .Equal, toItem: usernameField, attribute: .Bottom, multiplier: 1.0, constant: 0)
let constraintUsernameFieldVTop = NSLayoutConstraint(item: usernameField, attribute: .Top, relatedBy: .Equal, toItem: centerView, attribute: .Top, multiplier: 1.0, constant: 8)
let constraintUsernameFieldHTrailing = NSLayoutConstraint(item: usernameField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8)
let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Top, multiplier: 1.0, constant: 8)
let constraintPasswordLabelHLeading = NSLayoutConstraint(item: passwordLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel, attribute: .Trailing, relatedBy: .Equal, toItem: passwordField, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintPasswordLabelAlignBottom = NSLayoutConstraint(item: passwordLabel, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Bottom, multiplier: 1.0, constant: 0)
let constraintPasswordFieldHTrailing = NSLayoutConstraint(item: passwordField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8)
centerView.setTranslatesAutoresizingMaskIntoConstraints(false)
usernameLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
usernameField.setTranslatesAutoresizingMaskIntoConstraints(false)
passwordField.setTranslatesAutoresizingMaskIntoConstraints(false)
passwordLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
// submitButton.setTranslatesAutoresizingMaskIntoConstraints(false)
NSLayoutConstraint.activateConstraints([constraintCenterViewHeight, constraintCenterViewWidth, constraintCenterViewCenterX, constraintCenterViewCenterY, constraintUsernameLabelHLeading,
constraintUsernameLabelHTrailing, constraintUsernameLabelAlignBottom, constraintUsernameFieldVTop, constraintUsernameFieldHTrailing, constraintUsernameFieldVBottom, constraintPasswordLabelHLeading, constraintPasswordLabelHTrailing, constraintPasswordLabelAlignBottom, constraintPasswordFieldHTrailing])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My first question is: if the labels have an intrinsic content size,
and everything else is pinned to the yellow view, then why do I need
to define a fixed width and height? Why wouldn't it infer the width
and height from the intrinsic content of its subviews?
username
和 password
字段没有宽度。它们通过固定到 centerView
左右边缘的标签来获得宽度。如果您添加约束来为这些字段指定宽度,则 centerView
可以根据其内容确定其宽度。
Moving on and trying to recreate this layout in code was giving me an
error: Terminating app due to uncaught exception 'NSGenericException',
reason: 'Unable to activate constraint with items > and > because they
have no common ancestor. Does the constraint reference items in
different view hierarchies? That's illegal.'
您的第一个问题是您没有将 passwordLabel
添加为子视图:
self.centerView.addSubview(passwordLabel)
这就是导致您出错的原因。 passwordLabel
不在视图层次结构中,因此自动布局不知道如何使用 centerView
.
对其进行约束
您的第二个问题是您将 centerView
的 width
和 height
设置为 0
。尝试更大的值,例如 100
和 300
:
let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height,
relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0,
constant: 100)
let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width,
relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0,
constant: 300)
你的第三个问题是你的一些常量需要为负数:
// changed to -8
let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel,
attribute: .Trailing, relatedBy: .Equal, toItem: usernameField,
attribute: .Leading, multiplier: 1.0, constant: -8)
// changed to -8
let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField,
attribute: .Bottom, relatedBy: .Equal, toItem: passwordField,
attribute: .Top, multiplier: 1.0, constant: -8)
// changed to -8
let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel,
attribute: .Trailing, relatedBy: .Equal, toItem: passwordField,
attribute: .Leading, multiplier: 1.0, constant: -8)
我遇到了同样的错误,但发生的原因有所不同:
我收到错误是因为我引用了我的 superview before 我将视图添加到它的 superview。 <-- 这样编写代码与不包含 view.addSubview(stackView)
本身没有什么不同。两者都会产生相同的错误——因为视图与其父视图没有定义的关系。
在下面的 my 代码中,B1、B2 行发生在我将视图添加到超级视图之前(AA 行)。
这是我的代码:
class ViewController: UIViewController {
var label = UILabel()
var button = UIButton()
var stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.cyan
navigationItem.title = "VCTitle"
setupUI()
}
private func setupUI(){
label.backgroundColor = UIColor.blue
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.widthAnchor.constraint(equalToConstant: 80).isActive = true
button.backgroundColor = UIColor.purple
button.heightAnchor.constraint(equalToConstant: 30).isActive = true
button.widthAnchor.constraint(equalToConstant: 10).isActive = true
setupStackView()
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(button)
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView) // AA
}
private func setupStackView(){
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 15
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2
}
}
正确的做法是将 B1、B2 行移动到 AA 行之后的任意位置。
class ViewController: UIViewController {
var label = UILabel()
var button = UIButton()
var stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.cyan
navigationItem.title = "VCTitle"
setupUI()
}
private func setupUI(){
label.backgroundColor = UIColor.blue
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.widthAnchor.constraint(equalToConstant: 80).isActive = true
button.backgroundColor = UIColor.purple
button.heightAnchor.constraint(equalToConstant: 30).isActive = true
button.widthAnchor.constraint(equalToConstant: 10).isActive = true
setupStackView()
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(button)
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView) //AA
// The 2 lines below are now in the right place.
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2
}
private func setupStackView(){
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 15
}
}
我正在尝试了解 自动布局约束。在 Ray W 教程挑战(没有解决方案或讨论)之后,布局应如下所示:
在 IB 中做这件事很简单——创建一个黄色视图,具有宽度和高度,垂直居中,水平固定到边缘;然后在该视图中创建带有简单约束的标签、字段和按钮。
我的第一个问题是:如果标签具有固有的内容大小,而其他所有内容都固定在黄色视图中,那么为什么我需要定义固定的宽度和高度?为什么它不从其子视图的固有内容中推断出宽度和高度?
继续尝试在代码中重新创建此布局给我一个错误:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with items
<UILabel: 0x7a961d60; frame = (0 0; 0 0); text = 'Password:'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7a961e40>>
and<UIView: 0x7a96b6f0; frame = (0 0; 0 0); layer = <CALayer: 0x7a96b880>>
because they have no common ancestor. Does the constraint reference items in different view hierarchies? That's illegal.'
第二个问题:这些层是什么,我所有的视图都在 heirachy - superview 包含黄色视图包含文本标签和字段。
在经历了很多痛苦之后,我试图准确地重新创建在 IB 中所做的约束,但这只会增加以下错误: 无法同时满足约束条件。
(
"<NSLayoutConstraint:0x7ac57370 H:[UIView:0x7a96b6f0(0)]>",
"<NSLayoutConstraint:0x7ac57400 H:|-(8)-[UILabel:0x7a96bb50'Username:'] (Names: '|':UIView:0x7a96b6f0 )>",
"<NSLayoutConstraint:0x7ac57430 UILabel:0x7a96bb50'Username:'.trailing == UITextField:0x7a961020.leading + 8>",
"<NSLayoutConstraint:0x7ac57520 UITextField:0x7a961020.trailing == UIView:0x7a96b6f0.trailing - 8>" )
最后一个问题:我怎么知道视图 0x7aetc 是什么视图?我的代码中的这个约束在哪里?其他看起来还好(?).
我一定是在一些基本层面上做错了。
这是我的代码:
import UIKit
class ViewController: UIViewController {
let centerView = UIView()
let usernameLabel = UILabel()
let passwordLabel = UILabel()
let usernameField = UITextField()
let passwordField = UITextField()
let submitButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
centerView.backgroundColor = UIColor.yellowColor()
usernameLabel.text = "Username:"
passwordLabel.text = "Password:"
usernameField.borderStyle = .RoundedRect
passwordField.borderStyle = .RoundedRect
submitButton.setTitle("Submit!", forState: .Normal)
submitButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
submitButton.setTitleColor(UIColor.blueColor(), forState: .Highlighted)
view.addSubview(centerView)
self.centerView.addSubview(usernameField)
self.centerView.addSubview(passwordField)
self.centerView.addSubview(usernameLabel)
self.centerView.addSubview(submitButton)
let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0)
let constraintCenterViewCenterX = NSLayoutConstraint(item: centerView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1.0, constant: 0)
let constraintCenterViewCenterY = NSLayoutConstraint(item: centerView, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1.0, constant: 0)
let constraintUsernameLabelHLeading = NSLayoutConstraint(item: usernameLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel, attribute: .Trailing, relatedBy: .Equal, toItem: usernameField, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintUsernameLabelAlignBottom = NSLayoutConstraint(item: usernameLabel, attribute: .Bottom, relatedBy: .Equal, toItem: usernameField, attribute: .Bottom, multiplier: 1.0, constant: 0)
let constraintUsernameFieldVTop = NSLayoutConstraint(item: usernameField, attribute: .Top, relatedBy: .Equal, toItem: centerView, attribute: .Top, multiplier: 1.0, constant: 8)
let constraintUsernameFieldHTrailing = NSLayoutConstraint(item: usernameField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8)
let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Top, multiplier: 1.0, constant: 8)
let constraintPasswordLabelHLeading = NSLayoutConstraint(item: passwordLabel, attribute: .Leading, relatedBy: .Equal, toItem: centerView, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel, attribute: .Trailing, relatedBy: .Equal, toItem: passwordField, attribute: .Leading, multiplier: 1.0, constant: 8)
let constraintPasswordLabelAlignBottom = NSLayoutConstraint(item: passwordLabel, attribute: .Bottom, relatedBy: .Equal, toItem: passwordField, attribute: .Bottom, multiplier: 1.0, constant: 0)
let constraintPasswordFieldHTrailing = NSLayoutConstraint(item: passwordField, attribute: .Trailing, relatedBy: .Equal, toItem: centerView, attribute: .Trailing, multiplier: 1.0, constant: -8)
centerView.setTranslatesAutoresizingMaskIntoConstraints(false)
usernameLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
usernameField.setTranslatesAutoresizingMaskIntoConstraints(false)
passwordField.setTranslatesAutoresizingMaskIntoConstraints(false)
passwordLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
// submitButton.setTranslatesAutoresizingMaskIntoConstraints(false)
NSLayoutConstraint.activateConstraints([constraintCenterViewHeight, constraintCenterViewWidth, constraintCenterViewCenterX, constraintCenterViewCenterY, constraintUsernameLabelHLeading,
constraintUsernameLabelHTrailing, constraintUsernameLabelAlignBottom, constraintUsernameFieldVTop, constraintUsernameFieldHTrailing, constraintUsernameFieldVBottom, constraintPasswordLabelHLeading, constraintPasswordLabelHTrailing, constraintPasswordLabelAlignBottom, constraintPasswordFieldHTrailing])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My first question is: if the labels have an intrinsic content size, and everything else is pinned to the yellow view, then why do I need to define a fixed width and height? Why wouldn't it infer the width and height from the intrinsic content of its subviews?
username
和 password
字段没有宽度。它们通过固定到 centerView
左右边缘的标签来获得宽度。如果您添加约束来为这些字段指定宽度,则 centerView
可以根据其内容确定其宽度。
Moving on and trying to recreate this layout in code was giving me an error: Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with items > and > because they have no common ancestor. Does the constraint reference items in different view hierarchies? That's illegal.'
您的第一个问题是您没有将 passwordLabel
添加为子视图:
self.centerView.addSubview(passwordLabel)
这就是导致您出错的原因。 passwordLabel
不在视图层次结构中,因此自动布局不知道如何使用 centerView
.
您的第二个问题是您将 centerView
的 width
和 height
设置为 0
。尝试更大的值,例如 100
和 300
:
let constraintCenterViewHeight = NSLayoutConstraint(item: centerView, attribute: .Height,
relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0,
constant: 100)
let constraintCenterViewWidth = NSLayoutConstraint(item: centerView, attribute: .Width,
relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0,
constant: 300)
你的第三个问题是你的一些常量需要为负数:
// changed to -8
let constraintUsernameLabelHTrailing = NSLayoutConstraint(item: usernameLabel,
attribute: .Trailing, relatedBy: .Equal, toItem: usernameField,
attribute: .Leading, multiplier: 1.0, constant: -8)
// changed to -8
let constraintUsernameFieldVBottom = NSLayoutConstraint(item: usernameField,
attribute: .Bottom, relatedBy: .Equal, toItem: passwordField,
attribute: .Top, multiplier: 1.0, constant: -8)
// changed to -8
let constraintPasswordLabelHTrailing = NSLayoutConstraint(item: passwordLabel,
attribute: .Trailing, relatedBy: .Equal, toItem: passwordField,
attribute: .Leading, multiplier: 1.0, constant: -8)
我遇到了同样的错误,但发生的原因有所不同:
我收到错误是因为我引用了我的 superview before 我将视图添加到它的 superview。 <-- 这样编写代码与不包含 view.addSubview(stackView)
本身没有什么不同。两者都会产生相同的错误——因为视图与其父视图没有定义的关系。
在下面的 my 代码中,B1、B2 行发生在我将视图添加到超级视图之前(AA 行)。
这是我的代码:
class ViewController: UIViewController {
var label = UILabel()
var button = UIButton()
var stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.cyan
navigationItem.title = "VCTitle"
setupUI()
}
private func setupUI(){
label.backgroundColor = UIColor.blue
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.widthAnchor.constraint(equalToConstant: 80).isActive = true
button.backgroundColor = UIColor.purple
button.heightAnchor.constraint(equalToConstant: 30).isActive = true
button.widthAnchor.constraint(equalToConstant: 10).isActive = true
setupStackView()
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(button)
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView) // AA
}
private func setupStackView(){
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 15
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2
}
}
正确的做法是将 B1、B2 行移动到 AA 行之后的任意位置。
class ViewController: UIViewController {
var label = UILabel()
var button = UIButton()
var stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.cyan
navigationItem.title = "VCTitle"
setupUI()
}
private func setupUI(){
label.backgroundColor = UIColor.blue
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.widthAnchor.constraint(equalToConstant: 80).isActive = true
button.backgroundColor = UIColor.purple
button.heightAnchor.constraint(equalToConstant: 30).isActive = true
button.widthAnchor.constraint(equalToConstant: 10).isActive = true
setupStackView()
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(button)
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView) //AA
// The 2 lines below are now in the right place.
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true // B1
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true // B2
}
private func setupStackView(){
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 15
}
}