简体   繁体   中英

Conflicting layout constraints, translatesAutoresizingMaskIntoConstraints not working

First of all, this is what I want to achieve:

screenshot

The view needs to be centered, with a height of 200. The trailing an leading anchors should touch the layoutmargins. I am creating my constraints programatically.

import UIKit

class CustomView: UIView {

    var dialogView : UIView!

    func show()
    {
        UIApplication.shared.delegate?.window??.rootViewController?.view.addSubview(self)
        dialogView = UIView()
        dialogView.translatesAutoresizingMaskIntoConstraints = false

        dialogView.backgroundColor = .red
        addSubview(dialogView)

        let dialogViewCenterYConstraint = dialogView.centerYAnchor.constraint(equalTo: self.centerYAnchor)
        dialogViewCenterYConstraint.isActive = true

        let dialogViewHeightConstraint = dialogView.heightAnchor.constraint(equalToConstant: 200)
        dialogViewHeightConstraint.isActive = true

        let margins = self.layoutMarginsGuide

        let dialogViewLeadingConstraint = dialogView.leadingAnchor.constraint(equalTo: margins.leadingAnchor)
        dialogViewLeadingConstraint.isActive = true

        let dialogViewTrailingConstraint = dialogView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
        dialogViewTrailingConstraint.isActive = true
    }

    override func layoutSubviews() {
        frame = UIScreen.main.bounds
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        CustomView().show()
        // Do any additional setup after loading the view, typically from a nib.
    }

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


}

It is working, but it also prints the following warning:

[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:0x60000009ee60 h=--& v=--& ArtAlertView.CustomView:0x7f9f86c0f770.width == 0   (active)>",
    "<NSLayoutConstraint:0x60000009ed20 UIView:0x7f9f86c100d0.leading == UILayoutGuide:0x6000001b8b80'UIViewLayoutMarginsGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x60000009ed70 UIView:0x7f9f86c100d0.trailing == UILayoutGuide:0x6000001b8b80'UIViewLayoutMarginsGuide'.trailing   (active)>",
    "<NSLayoutConstraint:0x60000009eb90 'UIView-leftMargin-guide-constraint' H:|-(8)-[UILayoutGuide:0x6000001b8b80'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':ArtAlertView.CustomView:0x7f9f86c0f770 )>",
    "<NSLayoutConstraint:0x60000009ec30 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000001b8b80'UIViewLayoutMarginsGuide']-(8)-|(LTR)   (active, names: '|':ArtAlertView.CustomView:0x7f9f86c0f770 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000009ed70 UIView:0x7f9f86c100d0.trailing == UILayoutGuide:0x6000001b8b80'UIViewLayoutMarginsGuide'.trailing   (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.

I noticed one of the constraints is an NSAutoresizingMaskLayoutConstraint. I thought setting translatesAutoresizingMaskIntoConstraints to false would get rid of these.

Any thoughts?

Try the following:

func addSubview(_ view: UIView, with height: CGFloat = 200.0)
{
    //  Check whether superview is non-nil
    if view.superview != nil
    {
        view.removeFromSuperview()
    }
    //  Add self to view as subview
    self.addSubview(view)
    //  translatesAutoresizingMaskIntoConstraints is true by default, which breaks UIView.addConstraints() function
    view.translatesAutoresizingMaskIntoConstraints = false
    //  Create constraints
    let centerY = NSLayoutConstraint(item: view,
                                     attribute: .centerY,
                                     relatedBy: .equal,
                                     toItem: self,
                                     attribute: .centerY,
                                     multiplier: 1,
                                     constant: constants.top)
    let leading = NSLayoutConstraint(item: view,
                                     attribute: .leading,
                                     relatedBy: .equal,
                                     toItem: self,
                                     attribute: .leading,
                                     multiplier: 1,
                                     constant: constants.leading)
    let trailing = NSLayoutConstraint(item: view,
                                      attribute: .trailing,
                                      relatedBy: .equal,
                                      toItem: self,
                                      attribute: .trailing,
                                      multiplier: 1,
                                      constant: constants.trailing)
    //  Add constraints to superview and return them
    self.addConstraints([top, bottom, leading, trailing])

    let height = NSLayoutConstraint(item: view,
                                    attribute: .height,
                                    relatedBy: .equal,
                                    toItem: nil,
                                    attribute: nil,
                                    multiplier: 1,
                                    constant: height)
    view.addConstraints([height])
}

I'm not sure that this exact text will work however (height constraint in untested). The idea is to create new constraints for leading , trailing and centerY and add those to your CustomView intance. Height constraint must be added to the dialogView .

Because you create new CustomView without frame, when you called show a new dialogView will be added to it and layout with |-margin-[dialogView]-margin-| , this requires CustomView 's width >= 2 * margin . so you will get this layout warning.

There are 2 way to fix this issue:

1.when you initial a new CustomView give it a frame where frame.width >= margin * 2.

2.give leading and trailing constraint of dialogView a lower layout priority.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM