UIStackView 间距在未设置 updateConstraints 时打破约束
Posted
技术标签:
【中文标题】UIStackView 间距在未设置 updateConstraints 时打破约束【英文标题】:UIStackView spacing breaks constraints when not in set updateConstraints 【发布时间】:2018-03-23 15:24:36 【问题描述】:我有一个简单的ViewController
和一个名为MyView
的自定义子视图:
import UIKit
class ViewController: UIViewController
let myView = MyView()
override func viewDidLoad()
super.viewDidLoad()
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0).isActive = true
myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8.0).isActive = true
class MyView: UIView
let stackView: UIStackView
let label = UILabel()
let label2 = UILabel()
init()
stackView = UIStackView(arrangedSubviews: [label, label2])
super.init(frame: .zero)
stackView.axis = .vertical
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Label 1"
label2.translatesAutoresizingMaskIntoConstraints = false
label2.text = "Label 2"
stackView.spacing = 8.0
addSubview(stackView)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func updateConstraints()
super.updateConstraints()
stackView.fillSuperview()
当我运行它时,我在控制台中得到以下破坏性约束:
2018-03-23 16:11:58.960493+0100 ViewWithStackView[75612:10756278] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x608000280f00 'UISV-canvas-connection' UIStackView:0x7f8438e07510.top == UILabel:0x7f8438d06740'Label 1'.top (active)>",
"<NSLayoutConstraint:0x608000280fa0 'UISV-canvas-connection' V:[UILabel:0x7f8438e07790'Label 2']-(0)-| (active, names: '|':UIStackView:0x7f8438e07510 )>",
"<NSLayoutConstraint:0x608000280ff0 'UISV-spacing' V:[UILabel:0x7f8438d06740'Label 1']-(8)-[UILabel:0x7f8438e07790'Label 2'] (active)>",
"<NSLayoutConstraint:0x608000280550 'UIView-Encapsulated-Layout-Height' UIStackView:0x7f8438e07510.height == 0 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x608000280ff0 'UISV-spacing' V:[UILabel:0x7f8438d06740'Label 1']-(8)-[UILabel:0x7f8438e07790'Label 2'] (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2018-03-23 16:11:58.961737+0100 ViewWithStackView[75612:10756278]
[LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x6080002812c0 h=--& v=--& UIStackView:0x7f8438e07510.height == 0 (active)>",
"<NSLayoutConstraint:0x608000280f00 'UISV-canvas-connection' UIStackView:0x7f8438e07510.top == UILabel:0x7f8438d06740'Label 1'.top (active)>",
"<NSLayoutConstraint:0x608000280fa0 'UISV-canvas-connection' V:[UILabel:0x7f8438e07790'Label 2']-(0)-| (active, names: '|':UIStackView:0x7f8438e07510 )>",
"<NSLayoutConstraint:0x608000280ff0 'UISV-spacing' V:[UILabel:0x7f8438d06740'Label 1']-(8)-[UILabel:0x7f8438e07790'Label 2'] (active)>"
)
Will attempt to recover by breaking constraint
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
现在,如果我将以下行 stackView.spacing = 8.0
移动到 updateConstraints
方法,则约束不会中断。因此,以下代码可以正常工作,而不会在控制台中出现警告/错误:
import UIKit
class ViewController: UIViewController
let myView = MyView()
override func viewDidLoad()
super.viewDidLoad()
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0).isActive = true
myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8.0).isActive = true
class MyView: UIView
let stackView: UIStackView
let label = UILabel()
let label2 = UILabel()
init()
stackView = UIStackView(arrangedSubviews: [label, label2])
super.init(frame: .zero)
stackView.axis = .vertical
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Label 1"
label2.translatesAutoresizingMaskIntoConstraints = false
label2.text = "Label 2"
addSubview(stackView)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func updateConstraints()
super.updateConstraints()
stackView.fillSuperview()
stackView.spacing = 8.0
为什么将 stackView.spacing = 8.0
移动到 updateConstraints
可以解决此问题/删除警告/错误?
谢谢你的解释:)
【问题讨论】:
.fillSuperview()
发生了什么?
啊抱歉,它只是将顶部、尾部、底部和前导约束设置为 0。忘记取出辅助方法。我自己发现了这个问题......忘记设置 label.translatesAutoresizingMaskIntoConstraints = false。优雅...
【参考方案1】:
看起来这是你不想要的约束
"<NSLayoutConstraint:0x608000280550 'UIView-Encapsulated-Layout-Height' UIStackView:0x7f8438e07510.height == 0 (active)>"
我会尝试的第一件事是
stackView.translatesAutoresizingMaskIntoConstraints = false
另外,我不知道 stackView.fillSuperview()
在做什么,但你最好给它添加约束以填充视图。
【讨论】:
抱歉,忘记取出这个辅助方法了。它将顶部、尾部、底部和前导约束设置为 0 优雅的错误...真的忘记了 stackView.translatesAutoresizingMaskIntoConstraints = false...谢谢伙计!【参考方案2】:在第一种情况下,stackView 的高度为零,因为您还没有为它设置框架(在 fillSuperview()
之前的 init
中),因此在 2 个标签之间设置 8 的间距会导致冲突,但是在第二个框架为零,间距为零,根据(内在内容大小),2个标签的高度为零,因此,在这种情况下不会发生冲突,然后您在updateConstraints
中设置间距,但此时stackView有根据这条线 fillSuperview()
等于它的 superView 的框架,这样也顺利进行
【讨论】:
以上是关于UIStackView 间距在未设置 updateConstraints 时打破约束的主要内容,如果未能解决你的问题,请参考以下文章