使用代码创建约束 - 获取错误“无法同时满足约束”

时间:2016-07-18 21:06:47

标签: ios swift autolayout constraints

我在故事板中添加了一个UIView(称为swipedView),我没有为它设置任何自动布局约束。没有。现在在代码中,我想添加一些约束。为了测试它我想将它固定在屏幕的两侧(所以它是全屏)。

当我运行它时,我收到一条很长的错误消息,例如:

2016-07-18 22:59:07.990 FindTheWay[87145:18423835] 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:0x7ff02d11a6e0 V:|-(0)-[UIView:0x7ff02b479a40]   (Names: '|':UIView:0x7ff02b450100 )>",
    "<NSIBPrototypingLayoutConstraint:0x7ff02b416a50 'IB auto generated at build time for view with fixed frame' V:|-(20)-[UIView:0x7ff02b479a40]   (Names: '|':UIView:0x7ff02b450100 )>"
)

Will attempt to recover by breaking constraint 
<NSIBPrototypingLayoutConstraint:0x7ff02b416a50 'IB auto generated at build time for view with fixed frame' V:|-(20)-[UIView:0x7ff02b479a40]   (Names: '|':UIView:0x7ff02b450100 )>

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

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var swipedView: UIView!
    @IBOutlet weak var foregroundView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // that was a proposed fix to my problem I found in the internet. Didn't work
        view.translatesAutoresizingMaskIntoConstraints = false

    }

    override func viewDidAppear(animated: Bool) {

        let pinTop = NSLayoutConstraint(item: swipedView, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1.0, constant: 0)
        let pinLeft = NSLayoutConstraint(item: swipedView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0)
        let pinRight = NSLayoutConstraint(item: swipedView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0)
        let pinBottom = NSLayoutConstraint(item: swipedView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0)

        NSLayoutConstraint.activateConstraints([pinTop, pinLeft, pinRight, pinBottom])

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }    
}

我对通过代码设置约束非常陌生,所以我不知道如何处理这个问题。我检查了几个在stackOverflow上发现的类似问题,但不幸的是,这里没有任何帮助。

3 个答案:

答案 0 :(得分:2)

swipedView translatesAutoresizingMaskIntoConstraints设为false,而不是view

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var swipedView: UIView!
    @IBOutlet weak var foregroundView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // that was a proposed fix to my problem I found in the internet. Didn't work
        swipedView.translatesAutoresizingMaskIntoConstraints = false

    }

    override func viewDidAppear(animated: Bool) {

        let pinTop = NSLayoutConstraint(item: swipedView, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1.0, constant: 0)
        let pinLeft = NSLayoutConstraint(item: swipedView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0)
        let pinRight = NSLayoutConstraint(item: swipedView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0)
        let pinBottom = NSLayoutConstraint(item: swipedView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0)

        NSLayoutConstraint.activateConstraints([pinTop, pinLeft, pinRight, pinBottom])

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

此解决方案最终工作的原因可以在Apple's Documentation

中找到
  

请注意,自动调整遮罩约束完全指定视图的大小和位置;因此,您无法在不引入冲突的情况下添加其他约束来修改此大小或位置。

translatesAutoresizingMaskIntoConstraints设置为 true 时,我们说我们希望将相关视图的大小和位置转换为实际约束。

通过将translatesAutoresizingMaskIntoConstraints设置为 false ,我们说相关视图的大小和位置不应因任何原因而变成约束(在这种情况下,我们'重新创造我们自己的。)

由于我们希望应用修改view的大小和位置的约束,但实际上swipedView,我们需要设置swipedView translatesAutoresizingMaskIntoConstraints等于false

答案 1 :(得分:0)

我在使用界面构建器时遇到了同样的问题,解决方法是识别导致警告的约束(在这种情况下可能通过一次一个地注释掉它们),然后将该约束的优先级设置为999而不是1000(我认为是默认值)。以编程方式,您可以使用:

constraint.priority = 999

(用受影响的约束替换'约束'。) 这对我有用几次,不会影响布局,但会清除警告。我认为999相当于说“尽可能接近,但不要担心”,所以如果约束不能满足一小部分,你就不会得到警告。希望有所帮助。

答案 2 :(得分:0)

使用本文中提到的技术: http://travisjeffery.com/b/2013/11/preventing-ib-auto-generated-at-build-time-for-view-with-fixed-frame-when-using-auto-layout/

为什么它对我不起作用的原因是我用

做错了

view.translatesAutoresizingMaskIntoConstraints = false

必须是

swipedView.translatesAutoresizingMaskIntoConstraints = false

现在它有效。我不知道为什么(也许有些人可以解释一下?)

感谢@ZGski和@dan