以编程方式设置约束导致 Swift 中的冲突

Posted

技术标签:

【中文标题】以编程方式设置约束导致 Swift 中的冲突【英文标题】:Programmatically Setting Constraints Causes Conflict in Swift 【发布时间】:2016-04-19 02:46:02 【问题描述】:

正如我在 this GitHub issue 中发布的那样,我遇到了一些隐藏的约束问题,每当我尝试添加自己的约束时就会引发错误

2016-04-18 19:22:04.270 Metric Time[1519:447809] 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:0x15e670e70 h=--& v=--& Metric_Time.View:0x15e692e70.midX == + 115>",
"<NSLayoutConstraint:0x15e5048c0 Metric_Time.View:0x15e692e70.centerX == UIView:0x15e6953e0.centerX>",
"<NSAutoresizingMaskLayoutConstraint:0x15e55fd30 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' H:|-(0)-[UIView:0x15e6953e0]   (Names: '|':UIWindow:0x15e688ed0 )>",
"<NSLayoutConstraint:0x15e54e750 'UIView-Encapsulated-Layout-Width' H:[UIView:0x15e6953e0(320)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x15e5048c0 Metric_Time.View:0x15e692e70.centerX == UIView:0x15e6953e0.centerX>

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.`

我已经尝试寻找可以创建这些约束的位置,但是在我的 ViewController.swift 文件中搜索关键字,例如 constraintlayout .etc只有我写的代码。

如果有人想弄乱它,我的代码都在GitHub 上。

【问题讨论】:

【参考方案1】:

如果要以编程方式添加约束,则需要关闭 translateAutoresizingMaskIntoConstraints。您也没有足够的约束来满足布局引擎。请记住,UIView 没有固有大小,如果您在视图中使用自动布局,则需要使用约束设置所有内容,而不是依赖约束和框架的混合。一种可能的解决方案是添加一些代码,例如:

        self.view.addSubview(clockView)
        clockView.translatesAutoresizingMaskIntoConstraints = false
        clockView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor, constant: 0.0).active = true
        clockView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor, constant: 0.0).active = true
        clockView.widthAnchor.constraintEqualToConstant(230.0).active = true
        clockView.heightAnchor.constraintEqualToConstant(230.0).active = true

但是,这并不是您想要的,因为当它处于横向时,您的时钟会覆盖您的标签。但是你可以通过clockView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor, constant: 0.0).active = true来解决这个问题

【讨论】:

如果我在 UIDatePicker() 上使用它会怎样? 你可以做同样的事情,但是用 datePicker 替换clockView。您也不需要添加宽度和高度约束,因为 UIDatePicker 具有固有大小。 好的,@beyowulf,当我检查视图层次结构时,我的 UIDatePicker 看起来有点奇怪...imgur.com/y0sq2REgist.github.com/DeveloperACE/f551f8783e1fc01d600da3377c5308cd我做错了什么? @ACE 这就是 UIPickerViews 的实现方式。您无需担心,一般来说,Apple 框架都经过高度优化和强大。我为您的 repo github.com/DeveloperACE/MetricTime/pull/7 打开了一个拉取请求,您应该考虑这些更改。 有兼容 ios 8 的方法吗?

以上是关于以编程方式设置约束导致 Swift 中的冲突的主要内容,如果未能解决你的问题,请参考以下文章

iOS 以编程方式生成的视图具有隐藏的约束,导致与自动布局发生冲突

SnapKit 更新约束导致冲突

堆栈视图中的自动约束冲突、Swift 2、iOS 9.3、XCode 7

冲突约束(不存在)(Swift 4)

swift 自定义view VFL 设置约束冲突

X 位置约束未以编程方式更新 - Xcode 中的 Swift