不明确的布局(以编程方式添加的约束)
Ambiguous Layout (Programmatically Added Constraint)
我不知道为什么我以编程方式创建的约束不明确。我的应用程序在堆栈视图中有两个容器视图。其中一个容器视图 kanjiView
充当导航栏下方的下拉菜单 window。有人可以给我指出正确的方向吗?
override func viewDidLoad() {
super.viewDidLoad()
// Add Kanji View Container
let kanjiView = UIView()
view.addSubview(kanjiView)
// add child view controller view to container
let kanjiController = storyboard!.instantiateViewController(withIdentifier: "KanjiDictionaryTab")
addChild(kanjiController)
kanjiView.addSubview(kanjiController.view)
kanjiController.didMove(toParent: self)
// Add Safari View Container
let safariView = UIView()
view.addSubview(safariView)
// add child view controller view to container
let safariController = storyboard!.instantiateViewController(withIdentifier: "SafariTab")
addChild(safariController)
safariView.addSubview(safariController.view)
safariController.didMove(toParent: self)
//Create StackView
let stackView = UIStackView()
stackView.spacing = 0
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.alignment = .center
stackView.addArrangedSubview(kanjiView)
stackView.addArrangedSubview(safariView)
view.addSubview(stackView)
//Disable Autoresize
kanjiView.translatesAutoresizingMaskIntoConstraints = false
kanjiController.view.translatesAutoresizingMaskIntoConstraints = false
safariView.translatesAutoresizingMaskIntoConstraints = false
safariController.view.translatesAutoresizingMaskIntoConstraints = false
stackView.translatesAutoresizingMaskIntoConstraints = false
//self.view.translatesAutoresizingMaskIntoConstraints = false
//Add Constraints
NSLayoutConstraint.activate([
kanjiController.view.leadingAnchor.constraint(equalTo: kanjiView.leadingAnchor),
kanjiController.view.trailingAnchor.constraint(equalTo: kanjiView.trailingAnchor),
kanjiController.view.topAnchor.constraint(equalTo: kanjiView.topAnchor),
kanjiController.view.bottomAnchor.constraint(equalTo: kanjiView.bottomAnchor),
safariView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
safariView.heightAnchor.constraint(equalToConstant: self.view.frame.height*3/4),
kanjiView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
kanjiView.heightAnchor.constraint(equalToConstant: self.view.frame.height*1/4),
//kanjiView.heightAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.height*1/4),
safariController.view.leadingAnchor.constraint(equalTo: safariView.leadingAnchor),
safariController.view.trailingAnchor.constraint(equalTo: safariView.trailingAnchor),
safariController.view.topAnchor.constraint(equalTo: safariView.topAnchor),
safariController.view.bottomAnchor.constraint(equalTo: safariView.bottomAnchor),
//stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
//stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
stackView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
stackView.heightAnchor.constraint(equalToConstant: self.view.frame.height),
NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .top, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .bottom, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .bottom, multiplier: 1, constant: 0),
])
}
这是用来隐藏kanjiView
的函数:
func hideKanji() {
UIView.animate(withDuration: 0.35) {
self.kanjiView.isHidden.toggle()
self.stackView.layoutIfNeeded()
}
}
这是控制台中的输出警告:
(
"<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top (active)>",
"<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom (active)>",
"<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-| (active, names: '|':UIView:0x7ff2f6d1d990 )>",
"<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'] (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844 (active)>
(
"<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633 (active)>",
"<NSLayoutConstraint:0x6000021647d0 UIView:0x7ff2d6c116e0.height == 211 (active)>",
"<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top (active)>",
"<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom (active)>",
"<NSLayoutConstraint:0x600002151fe0 'UISV-canvas-connection' UIStackView:0x7ff2d6c12980.top == UIView:0x7ff2d6c116e0.top (active)>",
"<NSLayoutConstraint:0x6000021533e0 'UISV-canvas-connection' V:[UIView:0x7ff2d6c12810]-(0)-| (active, names: '|':UIStackView:0x7ff2d6c12980 )>",
"<NSLayoutConstraint:0x600002153430 'UISV-distributing-edge' V:[UIView:0x7ff2d6c116e0]-(0)-[_UIOLAGapGuide:0x600003e15e00'UISV-distributing'] (active)>",
"<NSLayoutConstraint:0x600002151f40 'UISV-distributing-edge' _UIOLAGapGuide:0x600003e15e00'UISV-distributing'.bottom == UIView:0x7ff2d6c12810.top (active)>",
"<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-| (active, names: '|':UIView:0x7ff2f6d1d990 )>",
"<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'] (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633 (active)>
我不确定这是否是问题所在,但在您的 NSLayoutConstraint.activate() 中,您正在为 stackView 设置锚点和边缘约束。选择其中之一,而不是两者。
您似乎将堆栈视图的顶部和底部锚定到本身设置高度的 layoutMArginGuide,并且还手动设置了高度。充其量,如果这两个值完全匹配,那就太过分了,如果它们相差一点点,就会产生无法满足的约束。失去明确的高度限制。
我不知道为什么我以编程方式创建的约束不明确。我的应用程序在堆栈视图中有两个容器视图。其中一个容器视图 kanjiView
充当导航栏下方的下拉菜单 window。有人可以给我指出正确的方向吗?
override func viewDidLoad() {
super.viewDidLoad()
// Add Kanji View Container
let kanjiView = UIView()
view.addSubview(kanjiView)
// add child view controller view to container
let kanjiController = storyboard!.instantiateViewController(withIdentifier: "KanjiDictionaryTab")
addChild(kanjiController)
kanjiView.addSubview(kanjiController.view)
kanjiController.didMove(toParent: self)
// Add Safari View Container
let safariView = UIView()
view.addSubview(safariView)
// add child view controller view to container
let safariController = storyboard!.instantiateViewController(withIdentifier: "SafariTab")
addChild(safariController)
safariView.addSubview(safariController.view)
safariController.didMove(toParent: self)
//Create StackView
let stackView = UIStackView()
stackView.spacing = 0
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.alignment = .center
stackView.addArrangedSubview(kanjiView)
stackView.addArrangedSubview(safariView)
view.addSubview(stackView)
//Disable Autoresize
kanjiView.translatesAutoresizingMaskIntoConstraints = false
kanjiController.view.translatesAutoresizingMaskIntoConstraints = false
safariView.translatesAutoresizingMaskIntoConstraints = false
safariController.view.translatesAutoresizingMaskIntoConstraints = false
stackView.translatesAutoresizingMaskIntoConstraints = false
//self.view.translatesAutoresizingMaskIntoConstraints = false
//Add Constraints
NSLayoutConstraint.activate([
kanjiController.view.leadingAnchor.constraint(equalTo: kanjiView.leadingAnchor),
kanjiController.view.trailingAnchor.constraint(equalTo: kanjiView.trailingAnchor),
kanjiController.view.topAnchor.constraint(equalTo: kanjiView.topAnchor),
kanjiController.view.bottomAnchor.constraint(equalTo: kanjiView.bottomAnchor),
safariView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
safariView.heightAnchor.constraint(equalToConstant: self.view.frame.height*3/4),
kanjiView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
kanjiView.heightAnchor.constraint(equalToConstant: self.view.frame.height*1/4),
//kanjiView.heightAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.height*1/4),
safariController.view.leadingAnchor.constraint(equalTo: safariView.leadingAnchor),
safariController.view.trailingAnchor.constraint(equalTo: safariView.trailingAnchor),
safariController.view.topAnchor.constraint(equalTo: safariView.topAnchor),
safariController.view.bottomAnchor.constraint(equalTo: safariView.bottomAnchor),
//stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
//stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
stackView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
stackView.heightAnchor.constraint(equalToConstant: self.view.frame.height),
NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .top, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0),
NSLayoutConstraint(item: stackView, attribute: .bottom, relatedBy: .equal, toItem: view.layoutMarginsGuide, attribute: .bottom, multiplier: 1, constant: 0),
])
}
这是用来隐藏kanjiView
的函数:
func hideKanji() {
UIView.animate(withDuration: 0.35) {
self.kanjiView.isHidden.toggle()
self.stackView.layoutIfNeeded()
}
}
这是控制台中的输出警告:
(
"<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top (active)>",
"<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom (active)>",
"<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-| (active, names: '|':UIView:0x7ff2f6d1d990 )>",
"<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'] (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000021649b0 UIStackView:0x7ff2d6c12980.height == 844 (active)>
(
"<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633 (active)>",
"<NSLayoutConstraint:0x6000021647d0 UIView:0x7ff2d6c116e0.height == 211 (active)>",
"<NSLayoutConstraint:0x600002164cd0 UIStackView:0x7ff2d6c12980.top == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.top (active)>",
"<NSLayoutConstraint:0x600002164dc0 UIStackView:0x7ff2d6c12980.bottom == UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'.bottom (active)>",
"<NSLayoutConstraint:0x600002151fe0 'UISV-canvas-connection' UIStackView:0x7ff2d6c12980.top == UIView:0x7ff2d6c116e0.top (active)>",
"<NSLayoutConstraint:0x6000021533e0 'UISV-canvas-connection' V:[UIView:0x7ff2d6c12810]-(0)-| (active, names: '|':UIStackView:0x7ff2d6c12980 )>",
"<NSLayoutConstraint:0x600002153430 'UISV-distributing-edge' V:[UIView:0x7ff2d6c116e0]-(0)-[_UIOLAGapGuide:0x600003e15e00'UISV-distributing'] (active)>",
"<NSLayoutConstraint:0x600002151f40 'UISV-distributing-edge' _UIOLAGapGuide:0x600003e15e00'UISV-distributing'.bottom == UIView:0x7ff2d6c12810.top (active)>",
"<NSLayoutConstraint:0x600002164aa0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide']-(83)-| (active, names: '|':UIView:0x7ff2f6d1d990 )>",
"<NSLayoutConstraint:0x600002153480 'UIView-Encapsulated-Layout-Height' UIView:0x7ff2f6d1d990.height == 844 (active)>",
"<NSLayoutConstraint:0x600002164a00 'UIView-topMargin-guide-constraint' V:|-(91)-[UILayoutGuide:0x600003b088c0'UIViewLayoutMarginsGuide'] (active, names: '|':UIView:0x7ff2f6d1d990 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002164730 UIView:0x7ff2d6c12810.height == 633 (active)>
我不确定这是否是问题所在,但在您的 NSLayoutConstraint.activate() 中,您正在为 stackView 设置锚点和边缘约束。选择其中之一,而不是两者。
您似乎将堆栈视图的顶部和底部锚定到本身设置高度的 layoutMArginGuide,并且还手动设置了高度。充其量,如果这两个值完全匹配,那就太过分了,如果它们相差一点点,就会产生无法满足的约束。失去明确的高度限制。