简体   繁体   中英

NSLayout Constraint inside UIStackView Unable to simultaneously satisfy constraints

I am creating a UIStackView inside of a UITableViewCell programatically. The StackView contains 3 message balloons, composed of container UIView, UIImageView and UILabel. I'm trying to make the container view's height larger than the image view, as it should include more elements on top of the UIImageView, but the height is cut down to the height of the UIImageView, and the console says Unable to simultaneously satisfy constraints . Getting advice from this answer I set UIImageView's translateAutoResizingMAskIntoConstraints to false, so now the container view is indeed taller than image view, but the image view's width does not fit to UILabel.

messageView.translatesAutoresizingMaskIntoConstraints = true(默认)

messageView.translatesAutoresizingMaskIntoConstraints = false

The code:

import UIKit
import PureLayout

@objc class ChatCell: UITableViewCell {

@IBOutlet weak var view: UIView!
@IBOutlet weak var headerView: UIView!
@IBOutlet weak var showMoreButton: UIButton!


override func awakeFromNib() {
    super.awakeFromNib()
    
    // stack view
    let stackView = UIStackView()
    stackView.axis = NSLayoutConstraint.Axis.vertical
    stackView.distribution = UIStackView.Distribution.equalSpacing
    stackView.alignment = UIStackView.Alignment.center
    stackView.spacing = 16.0
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    // bubble colors
    var colors = [UIColor]()
    colors.append(UIColor(red: 30/255, green: 222/255, blue: 38/255, alpha: 1))
    colors.append(UIColor(red: 20/255, green: 80/255, blue: 210/255, alpha: 1))
    colors.append(UIColor(red: 150/255, green: 120/255, blue: 30/255, alpha: 1))
    
    for color in colors {
        stackView.addArrangedSubview(addMessage(color: color, text: "לורם איפסום דולור סיט אמט, קונסקטורר אדיפיסינג אלית קולורס מרגשי ומרגשח. עמחליף לורם איפסום דולור סיט אמט, קונסקטורר אדיפיסינג אלית. סת אלמנקום ניסי נון ניבאה."))
    }
    
    view.addSubview(stackView)
    stackView.autoPinEdge(.top, to: .bottom, of: headerView, withOffset: 30)
    stackView.autoPinEdge(.bottom, to: .top, of: showMoreButton, withOffset: -30)
    stackView.autoCenterInSuperview()
}

func addMessage(color: UIColor, text: String) -> UIView {
    let containerView = UIView(frame: .zero)
    let label = UILabel()
    var messageView = UIImageView()
    
    setText(label, text)
    setTextBubble(label, &messageView, color)
    
    containerView.addSubview(messageView)

    containerView.translatesAutoresizingMaskIntoConstraints = false
    
    containerView.autoMatch(.width, to: .width, of: messageView)
    containerView.autoPinEdge(.bottom, to: .bottom, of: messageView)
    containerView.autoPinEdge(.top, to: .top, of: messageView, withOffset: -20)
    containerView.autoAlignAxis(.horizontal, toSameAxisOf: messageView)
    containerView.backgroundColor = .red
    
    label.center = messageView.center
    containerView.addSubview(label)
    view.addSubview(containerView)
    
    return containerView
}

fileprivate func setText(_ label: UILabel, _ text: String) {
    label.numberOfLines = 2
    label.font = UIFont.init(name: "South-Light", size: 18)
    label.textColor = .white
    label.text = text
    label.textAlignment = NSTextAlignment.right
    
    // set text frame
    let TEXT_FRAME_HEIGHT = 60.0
    let constraintRect = CGSize(width: 0.66 * Double(view.frame.width), height: TEXT_FRAME_HEIGHT)
    let boundingBox = text.boundingRect(with: constraintRect,
                                        options: .usesLineFragmentOrigin,
                                        attributes: [.font: label.font],
                                        context: nil)
    label.frame.size = CGSize(width:ceil(boundingBox.width),
                              height: ceil(boundingBox.height))
}

fileprivate func setTextBubble(_ label: UILabel, _ messageView: inout UIImageView, _ color: UIColor) {
    // set text bubble
    let bubbleImageSize = CGSize(width: label.frame.width + 28,
                                 height: label.frame.height + 20)
    
    messageView = UIImageView(frame:
        CGRect(x: 0,
               y: 0,//view.frame.height - bubbleImageSize.height - 5,
            width: bubbleImageSize.width,
            height: bubbleImageSize.height))
    
    let bubbleImage = UIImage(named: "incoming-message-bubble")?
        .resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21,
                                                    bottom: 17, right: 21), resizingMode: .stretch)
        .withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
    
    messageView.image = bubbleImage
    messageView.tintColor = color
    // this line changes layout
    messageView.translatesAutoresizingMaskIntoConstraints = false
}
}

console log:

   2020-07-26 13:13:54.040496+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (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:0x2801c7570 V:[UIImageView:0x155dc1dd0]-(0)-|   (active, names: '|':UIView:0x155dc0570 )>",
    "<NSLayoutConstraint:0x2801c75c0 UIView:0x155dc0570.top == UIImageView:0x155dc1dd0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7610 UIView:0x155dc0570.centerY == UIImageView:0x155dc1dd0.centerY   (active)>"
ng constraint 
<NSLayoutConstraint:0x2801c7610 UIView:0x155dc0570.centerY == UIImageView:0x155dc1dd0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:54.041636+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (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:0x2801c77f0 V:[UIImageView:0x155dc27d0]-(0)-|   (active, names: '|':UIView:0x155dc3410 )>",
NSLayoutConstraint:0x2801c7840 UIView:0x155dc3410.top == UIImageView:0x155dc27d0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7890 UIView:0x155dc3410.centerY == UIImageView:0x155dc27d0.centerY   (active)>"
ng constraint 
<NSLayoutConstraint:0x2801c7890 UIView:0x155dc3410.centerY == UIImageView:0x155dc27d0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:54.042503+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (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:0x2801c7a70 V:[UIImageView:0x155dc40c0]-(0)-|   (active, names: '|':UIView:0x155dc3b00 )>",
    "<NSLayoutConstraint:0x2801c7ac0 UIView:0x155dc3b00.top == UIImageView:0x155dc40c0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7b10 UIView:0x155dc3b00.centerY == UIImageView:0x155dc40c0.centerY   (active)>"
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x2801c7b10 UIView:0x155dc3b00.centerY == UIImageView:0x155dc40c0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:58.655384+0300 Sport5[10267:1581233] [LayoutConstraints] Window has a view with an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.849727+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.855433+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.865918+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES ```

The first complaint from the layout manager is very obvious. You have one constraint that x.top = y.top and another that x.top = y.top - 20. You produced the constraints, you should be able to fix them. I didn't look any further.

As it turned out, the problem was that UIStackView is based on intrinsic content size of it's subviews, so I had to add constraints to sizes instead of using frames. afterwards I added the UILabel as subview of UIImageView and set leading trailing and center constraints, and that fixed the issue. I didn't accept @gnasher729 as this wasn't the correct answer, but it did gave me a hint to solve it, and for that I appreciate his help.

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