UIStackView中的NSLayout约束无法同时满足约束

时间:2020-07-26 10:31:37

标签: ios swift

我正在以编程方式在UITableViewCell内部创建一个UIStackView。 StackView包含3个消息气球,由容器UIView,UIImageView和UILabel组成。 我正在尝试使容器视图的高度大于图像视图的高度,因为它应该在UIImageView的顶部包含更多元素,但是高度会降低到UIImageView的高度,并且控制台会显示Unable to simultaneously satisfy constraints 。 从this answer获得建议,我将UIImageView的translateAutoResizingMAskIntoConstraints设置为false,因此现在容器视图的确比图像视图高,但是图像视图的宽度不适合UILabel。

messageView.translatesAutoresizingMaskIntoConstraints = true (default)

messageView.translatesAutoresizingMaskIntoConstraints = false

代码:

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
}
}

控制台日志:

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

2 个答案:

答案 0 :(得分:0)

布局经理的第一个抱怨非常明显。您有一个约束x.top = y.top,另一个约束x.top = y.top-20。产生了约束,您应该能够修复它们。我没再看了。

答案 1 :(得分:0)

事实证明,问题在于UIStackView基于其子视图的内在内容大小,因此我不得不对大小添加约束,而不是使用框架。之后,我将UILabel添加为UIImageView的子视图,并设置了领先的尾随和居中约束,从而解决了该问题。 我不接受@ gnasher729,因为这不是正确的答案,但这确实给了我解决的提示,为此,我感谢他的帮助。