简体   繁体   English

为什么嵌入的 UIStackView,按比例填充,间距和布局边距会导致约束错误以及如何修复?

[英]Why do embedded UIStackView's, filled Proportionally, with spacing and Layout Margins causes constraint errors and how to fix?

This question comes off the back of the great question and answer at:这个问题来自伟大问答的背后:

Stackoverflow: Why does a UIStackView with a single view, fill Proportionally, and Layout Margins causes ambiguous constraint error? Stackoverflow:为什么单视图的UIStackView,按比例填充,和Layout Margins会导致模糊约束错误?

I am having similar issues but with embedded stackviews inside a scrollview.我有类似的问题,但在滚动视图中嵌入了堆栈视图。 I have modified the explanation code from the above question.我已经修改了上述问题的解释代码。 In my working code, I have a parentVC that loads into a container view, a childVC that has the embedded scrollView and stackViews (outer stackview is vertical and then each of its subviews are a bunch of horizontal stackviews).在我的工作代码中,我有一个加载到容器视图中的 parentVC,一个具有嵌入式 scrollView 和 stackViews 的 childVC(外部 stackview 是垂直的,然后它的每个子视图都是一堆水平的 stackviews)。 There are a range of options from fixed width label, icons and expanding labels.有一系列选项,包括固定宽度 label、图标和扩展标签。

The problem is I either get UISV-spacing constraint errors or trailing errors for the expanding labels.问题是我得到 UISV 间距约束错误或扩展标签的尾随错误。 I understand from the above question that this has to do with the sequence of how the auto layout engine is calculating the proportional widths, spacing etc. but have no idea how to fix.我从上述问题中了解到,这与自动布局引擎如何计算比例宽度、间距等的顺序有关,但不知道如何解决。 Any suggestions would be welcome.欢迎大家提出意见。 I'm attaching the code I'm using:我附上了我正在使用的代码:

class ParentVC: UIViewController {
    
    override func viewDidLoad() {
        
        let vcContainer = UIView()
        view.addSubview(vcContainer)
        vcContainer.backgroundColor = .systemYellow
        vcContainer.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            vcContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
            vcContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -150),
            vcContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
            vcContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50),
        ])
        
        let vc = ChildVC()
        addChild(vc)
        vc.didMove(toParent: self)
        vcContainer.addSubview(vc.view)
        vc.view.frame = vcContainer.bounds
        vc.view.heightAnchor.constraint(equalTo: vcContainer.heightAnchor).isActive = true
    }
    
}

class ChildVC: UIViewController {

    let outerStackView: UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .vertical
        v.spacing = 8
        return v
    }()

    let scrollView: UIScrollView = {
        let sv = UIScrollView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        return sv
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        for _ in 1...7 {
            let lbl = UILabel()
            lbl.font = UIFont.systemFont(ofSize: 12.0, weight: .light)
            lbl.numberOfLines = 0
            lbl.textAlignment = .center
            outerStackView.addArrangedSubview(lbl)
            let sv = UIStackView()
            sv.translatesAutoresizingMaskIntoConstraints = false
            sv.axis = .horizontal
            sv.distribution = .fillProportionally
            sv.spacing = 10
            outerStackView.addArrangedSubview(sv)
        }

        view.addSubview(scrollView)
        scrollView.addSubview(outerStackView)

        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.widthAnchor.constraint(equalTo: view.widthAnchor),
            scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            scrollView.heightAnchor.constraint(equalTo: view.heightAnchor),
            
            outerStackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
            outerStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            outerStackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
            outerStackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
            outerStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
        ])

        // StackView 1
        if let lbl = outerStackView.arrangedSubviews[0] as? UILabel,
            let sv = outerStackView.arrangedSubviews[1] as? UIStackView {

            let v = ExpandingLabel()
            sv.addArrangedSubview(v)

            lbl.text = "SV1: One view \n no layoutMargins"
        }

        // StackView 2
        if let lbl = outerStackView.arrangedSubviews[2] as? UILabel,
            let sv = outerStackView.arrangedSubviews[3] as? UIStackView {


            let v = FixedLabel()
            sv.addArrangedSubview(v)


            let v2 = ExpandingLabel()
            sv.addArrangedSubview(v2)

            lbl.text = "SV2: Two views \n no layoutMargins"
        }

        // comment out this block to see the auto-layout error goes away
        // StackView 3
        if let lbl = outerStackView.arrangedSubviews[4] as? UILabel,
            let sv = outerStackView.arrangedSubviews[5] as? UIStackView {


            let v = ExpandingLabel()
            sv.addArrangedSubview(v)

            sv.isLayoutMarginsRelativeArrangement = true
            sv.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 11)

            lbl.text = "SV3: One view\nlayoutMargins left: \(sv.layoutMargins.left), right: \(sv.layoutMargins.right)"
        }

        // StackView 4
        if let lbl = outerStackView.arrangedSubviews[6] as? UILabel,
            let sv = outerStackView.arrangedSubviews[7] as? UIStackView {

            let v = FixedLabel()
            sv.addArrangedSubview(v)

            let v2 = ExpandingLabel()
            sv.addArrangedSubview(v2)

            sv.isLayoutMarginsRelativeArrangement = true
            sv.layoutMargins = .init(top: 0, left: 12, bottom: 0, right: 13)
    
            lbl.text = "SV4: Two views\nlayoutMargins\n left:  \(sv.layoutMargins.left), right: \(sv.layoutMargins.right)"
        }

        // StackView 5
        if let lbl = outerStackView.arrangedSubviews[8] as? UILabel,
            let sv = outerStackView.arrangedSubviews[9] as? UIStackView {

            let v = FixedLabel()
            sv.addArrangedSubview(v)

            let v2 = ExpandingLabel()
            sv.addArrangedSubview(v2)

            sv.isLayoutMarginsRelativeArrangement = true
            sv.layoutMargins = .init(top: 0, left: 101, bottom: 0, right: 0)

            lbl.text = "SV5: Two views \nlayoutMargins left:  \(sv.layoutMargins.left), right: \(sv.layoutMargins.right)"
        }

        // StackView 6
        if let lbl = outerStackView.arrangedSubviews[10] as? UILabel,
            let sv = outerStackView.arrangedSubviews[11] as? UIStackView {

            let v = IconView()
            sv.addArrangedSubview(v)

            let v2 = ExpandingLabel()
            v2.numberOfLines = 0
            sv.addArrangedSubview(v2)

            sv.isLayoutMarginsRelativeArrangement = true
            sv.layoutMargins = .init(top: 0, left: 14, bottom: 0, right: 15)

            lbl.text = "SV6: Two views\nlayoutMargins left:  \(sv.layoutMargins.left), right: \(sv.layoutMargins.right)"
        }
        
        
        // StackView 7
        if let lbl = outerStackView.arrangedSubviews[12] as? UILabel,
            let sv = outerStackView.arrangedSubviews[13] as? UIStackView {


            let v = ExpandingLabel()
            sv.addArrangedSubview(v)

            sv.isLayoutMarginsRelativeArrangement = true
            sv.layoutMargins = .init(top: 0, left: 16, bottom: 0, right: 17)

            let v2 = ExpandingLabel()
            sv.addArrangedSubview(v2)

            lbl.text = "SV7: One view\nlayoutMargins left:  \(sv.layoutMargins.left), right: \(sv.layoutMargins.right)"
        }
    }

}


class IconView: UIImageView {
     init() {
        super.init(frame: .zero)
    
        self.backgroundColor = UIColor.systemRed
        self.tintColor = .white

        image = UIImage(systemName: "square.and.arrow.up")?.applyingSymbolConfiguration(UIImage.SymbolConfiguration(textStyle: .body))
        contentMode = .center
        
        translatesAutoresizingMaskIntoConstraints = false
        adjustsImageSizeForAccessibilityContentSizeCategory = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class FixedLabel : UILabel {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        text = "fxd"
        backgroundColor = .systemRed
        
        translatesAutoresizingMaskIntoConstraints = false
        setContentCompressionResistancePriority(.required, for: .horizontal)
        setContentHuggingPriority(.required, for: .horizontal)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class ExpandingLabel: UILabel {
  
    override init(frame: CGRect) {
        super.init(frame: frame)
        text = "expanding label"
        backgroundColor = .systemGreen
        numberOfLines = 3
        font = UIFont.preferredFont(forTextStyle: .body)
        adjustsFontForContentSizeCategory = true

        translatesAutoresizingMaskIntoConstraints = false
        setContentHuggingPriority(.defaultLow, for: .horizontal)
        setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
        setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

The above produces the desired result as per below:上述产生的预期结果如下:

在此处输入图像描述

The log errors are:日志错误是:

2021-03-16 10:01:22.815997+1100 stackviewsWithProportionalFill[8528:4745644] Sherlock initialised 2021-03-16 10:01:23.051125+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x600003317e80 'UISV-canvas-connection' UIStackView:0x7feb0270f930.leading == stackviewsWithProportionalFill.FixedLabel:0x7feb02715f80.leading   (active)>",
    "<NSLayoutConstraint:0x600003317930 'UISV-canvas-connection' H:[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0270b710]-(0)-| (active, names: '|':UIStackView:0x7feb0270f930 )>",
    "<NSLayoutConstraint:0x6000033172a0 'UISV-fill-proportionally' stackviewsWithProportionalFill.ExpandingLabel:0x7feb0270b710.width == UIStackView:0x7feb0270f930.width   (active)>",
    "<NSLayoutConstraint:0x6000033178e0 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02715f80]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0270b710] (active)>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x6000033178e0 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02715f80]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0270b710] (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. 2021-03-16 10:01:23.057974+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x60000332cb40 UIScrollView:0x7feb0381ea00.width == UIView:0x7feb0270aeb0.width   (active)>",
    "<NSLayoutConstraint:0x60000332d270 UIStackView:0x7feb02709160.width == UIScrollView:0x7feb0381ea00.width  (active)>",
    "<NSLayoutConstraint:0x600003370fa0 'UISV-alignment' UILabel:0x7feb0270b2a0.leading == UIStackView:0x7feb02711930.leading   (active)>",
    "<NSLayoutConstraint:0x6000033713b0 'UISV-alignment' UILabel:0x7feb0270b2a0.trailing == UIStackView:0x7feb02711930.trailing (active)>",
    "<NSLayoutConstraint:0x600003310eb0 'UISV-canvas-connection' UILayoutGuide:0x6000029208c0'UIViewLayoutMarginsGuide'.leading == stackviewsWithProportionalFill.FixedLabel:0x7feb02717140.leading   (active)>",
    "<NSLayoutConstraint:0x6000033123f0 'UISV-canvas-connection' UILayoutGuide:0x6000029208c0'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb02717530.trailing  (active)>",
    "<NSLayoutConstraint:0x600003370c80 'UISV-canvas-connection' UIStackView:0x7feb02709160.leading == UILabel:0x7feb0270b2a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003370cd0 'UISV-canvas-connection' H:[UILabel:0x7feb0270b2a0]-(0)-|   (active, names: '|':UIStackView:0x7feb02709160 )>",
    "<NSLayoutConstraint:0x600003312530 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02717140]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb02717530] (active)>",
    "<NSLayoutConstraint:0x600003371540 'UIView-Encapsulated-Layout-Width' UIView:0x7feb0270aeb0.width == 0   (active)>",
    "<NSLayoutConstraint:0x600003312300 'UIView-leftMargin-guide-constraint' H:|-(101)-[UILayoutGuide:0x6000029208c0'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7feb02711930 )>",
    "<NSLayoutConstraint:0x6000033123a0 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000029208c0'UIViewLayoutMarginsGuide']-(0)-|(LTR)  (active, names: '|':UIStackView:0x7feb02711930 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x600003312530 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02717140]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb02717530] (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. 2021-03-16 10:01:23.065566+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x60000332cb40 UIScrollView:0x7feb0381ea00.width == UIView:0x7feb0270aeb0.width   (active)>",
    "<NSLayoutConstraint:0x60000332d270 UIStackView:0x7feb02709160.width == UIScrollView:0x7feb0381ea00.width  (active)>",
    "<NSLayoutConstraint:0x6000033710e0 'UISV-alignment' UILabel:0x7feb0270b2a0.leading == UIStackView:0x7feb02712730.leading   (active)>",
    "<NSLayoutConstraint:0x6000033714f0 'UISV-alignment' UILabel:0x7feb0270b2a0.trailing == UIStackView:0x7feb02712730.trailing (active)>",
    "<NSLayoutConstraint:0x6000033138e0 'UISV-canvas-connection' UILayoutGuide:0x600002920a80'UIViewLayoutMarginsGuide'.leading == stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e660.leading   (active)>",
    "<NSLayoutConstraint:0x600003313930 'UISV-canvas-connection' UILayoutGuide:0x600002920a80'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260ecd0.trailing  (active)>",
    "<NSLayoutConstraint:0x600003370c80 'UISV-canvas-connection' UIStackView:0x7feb02709160.leading == UILabel:0x7feb0270b2a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003370cd0 'UISV-canvas-connection' H:[UILabel:0x7feb0270b2a0]-(0)-|   (active, names: '|':UIStackView:0x7feb02709160 )>",
    "<NSLayoutConstraint:0x600003370050 'UISV-spacing' H:[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e660]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260ecd0] (active)>",
    "<NSLayoutConstraint:0x600003371540 'UIView-Encapsulated-Layout-Width' UIView:0x7feb0270aeb0.width == 0   (active)>",
    "<NSLayoutConstraint:0x6000033137f0 'UIView-leftMargin-guide-constraint' H:|-(16)-[UILayoutGuide:0x600002920a80'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7feb02712730 )>",
    "<NSLayoutConstraint:0x600003313890 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600002920a80'UIViewLayoutMarginsGuide']-(17)-|(LTR) (active, names: '|':UIStackView:0x7feb02712730 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x600003370050 'UISV-spacing' H:[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e660]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260ecd0] (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. 2021-03-16 10:01:23.066504+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x60000332cb40 UIScrollView:0x7feb0381ea00.width == UIView:0x7feb0270aeb0.width   (active)>",
    "<NSLayoutConstraint:0x60000332d270 UIStackView:0x7feb02709160.width == UIScrollView:0x7feb0381ea00.width  (active)>",
    "<NSLayoutConstraint:0x600003371040 'UISV-alignment' UILabel:0x7feb0270b2a0.leading == UIStackView:0x7feb02712130.leading   (active)>",
    "<NSLayoutConstraint:0x600003371450 'UISV-alignment' UILabel:0x7feb0270b2a0.trailing == UIStackView:0x7feb02712130.trailing (active)>",
    "<NSLayoutConstraint:0x600003312e90 'UISV-canvas-connection' UILayoutGuide:0x600002920b60'UIViewLayoutMarginsGuide'.leading == stackviewsWithProportionalFill.IconView:0x7feb027179a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003312ee0 'UISV-canvas-connection' UILayoutGuide:0x600002920b60'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e1f0.trailing  (active)>",
    "<NSLayoutConstraint:0x600003370c80 'UISV-canvas-connection' UIStackView:0x7feb02709160.leading == UILabel:0x7feb0270b2a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003370cd0 'UISV-canvas-connection' H:[UILabel:0x7feb0270b2a0]-(0)-|   (active, names: '|':UIStackView:0x7feb02709160 )>",
    "<NSLayoutConstraint:0x600003313020 'UISV-spacing' H:[stackviewsWithProportionalFill.IconView:0x7feb027179a0]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e1f0] (active)>",
    "<NSLayoutConstraint:0x600003371540 'UIView-Encapsulated-Layout-Width' UIView:0x7feb0270aeb0.width == 0   (active)>",
    "<NSLayoutConstraint:0x600003312da0 'UIView-leftMargin-guide-constraint' H:|-(14)-[UILayoutGuide:0x600002920b60'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7feb02712130 )>",
    "<NSLayoutConstraint:0x600003312e40 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600002920b60'UIViewLayoutMarginsGuide']-(15)-|(LTR) (active, names: '|':UIStackView:0x7feb02712130 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x600003313020 'UISV-spacing' H:[stackviewsWithProportionalFill.IconView:0x7feb027179a0]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb0260e1f0] (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. 2021-03-16 10:01:23.067723+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x60000332cb40 UIScrollView:0x7feb0381ea00.width == UIView:0x7feb0270aeb0.width   (active)>",
    "<NSLayoutConstraint:0x60000332d270 UIStackView:0x7feb02709160.width == UIScrollView:0x7feb0381ea00.width  (active)>",
    "<NSLayoutConstraint:0x600003370f00 'UISV-alignment' UILabel:0x7feb0270b2a0.leading == UIStackView:0x7feb02710b30.leading   (active)>",
    "<NSLayoutConstraint:0x600003371310 'UISV-alignment' UILabel:0x7feb0270b2a0.trailing == UIStackView:0x7feb02710b30.trailing (active)>",
    "<NSLayoutConstraint:0x6000033118b0 'UISV-canvas-connection' UILayoutGuide:0x600002920380'UIViewLayoutMarginsGuide'.leading == stackviewsWithProportionalFill.FixedLabel:0x7feb02716a60.leading   (active)>",
    "<NSLayoutConstraint:0x600003311900 'UISV-canvas-connection' UILayoutGuide:0x600002920380'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb02716cd0.trailing  (active)>",
    "<NSLayoutConstraint:0x600003370c80 'UISV-canvas-connection' UIStackView:0x7feb02709160.leading == UILabel:0x7feb0270b2a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003370cd0 'UISV-canvas-connection' H:[UILabel:0x7feb0270b2a0]-(0)-|   (active, names: '|':UIStackView:0x7feb02709160 )>",
    "<NSLayoutConstraint:0x600003311a40 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02716a60]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb02716cd0] (active)>",
    "<NSLayoutConstraint:0x600003371540 'UIView-Encapsulated-Layout-Width' UIView:0x7feb0270aeb0.width == 0   (active)>",
    "<NSLayoutConstraint:0x6000033117c0 'UIView-leftMargin-guide-constraint' H:|-(12)-[UILayoutGuide:0x600002920380'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7feb02710b30 )>",
    "<NSLayoutConstraint:0x600003311860 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600002920380'UIViewLayoutMarginsGuide']-(13)-|(LTR) (active, names: '|':UIStackView:0x7feb02710b30 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x600003311a40 'UISV-spacing' H:[stackviewsWithProportionalFill.FixedLabel:0x7feb02716a60]-(10)-[stackviewsWithProportionalFill.ExpandingLabel:0x7feb02716cd0] (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. 2021-03-16 10:01:23.068649+1100 stackviewsWithProportionalFill[8528:4745644] [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.  (
    "<NSLayoutConstraint:0x60000332cb40 UIScrollView:0x7feb0381ea00.width == UIView:0x7feb0270aeb0.width   (active)>",
    "<NSLayoutConstraint:0x60000332d270 UIStackView:0x7feb02709160.width == UIScrollView:0x7feb0381ea00.width  (active)>",
    "<NSLayoutConstraint:0x600003370e60 'UISV-alignment' UILabel:0x7feb0270b2a0.leading == UIStackView:0x7feb02710130.leading   (active)>",
    "<NSLayoutConstraint:0x600003371270 'UISV-alignment' UILabel:0x7feb0270b2a0.trailing == UIStackView:0x7feb02710130.trailing (active)>",
    "<NSLayoutConstraint:0x600003316df0 'UISV-canvas-connection' UILayoutGuide:0x600002939880'UIViewLayoutMarginsGuide'.leading == stackviewsWithProportionalFill.ExpandingLabel:0x7feb027167f0.leading   (active)>",
    "<NSLayoutConstraint:0x600003316da0 'UISV-canvas-connection' UILayoutGuide:0x600002939880'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb027167f0.trailing  (active)>",
    "<NSLayoutConstraint:0x600003370c80 'UISV-canvas-connection' UIStackView:0x7feb02709160.leading == UILabel:0x7feb0270b2a0.leading   (active)>",
    "<NSLayoutConstraint:0x600003370cd0 'UISV-canvas-connection' H:[UILabel:0x7feb0270b2a0]-(0)-|   (active, names: '|':UIStackView:0x7feb02709160 )>",
    "<NSLayoutConstraint:0x600003371540 'UIView-Encapsulated-Layout-Width' UIView:0x7feb0270aeb0.width == 0   (active)>",
    "<NSLayoutConstraint:0x600003316ee0 'UIView-leftMargin-guide-constraint' H:|-(10)-[UILayoutGuide:0x600002939880'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7feb02710130 )>",
    "<NSLayoutConstraint:0x600003316e40 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600002939880'UIViewLayoutMarginsGuide']-(11)-|(LTR) (active, names: '|':UIStackView:0x7feb02710130 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x600003316da0 'UISV-canvas-connection' UILayoutGuide:0x600002939880'UIViewLayoutMarginsGuide'.trailing == stackviewsWithProportionalFill.ExpandingLabel:0x7feb027167f0.trailing  (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. 2021-03-16 10:01:24.091972+1100 stackviewsWithProportionalFill[8528:4745811] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed

You have inadvertently presented one of the (many) reasons I tell people to *forget you ever heard of the .fillProportionally Distribution property of a UIStackView ...您无意中提出了我告诉人们*忘记您听说过UIStackView.fillProportionally Distribution 属性的(许多)原因之一...

For your horizontal stack views, you have:对于您的水平堆栈视图,您有:

sv.distribution = .fillProportionally

So you just told auto-layout: "Stretch the widths of the arranged subviews proportionally to each other!"所以你只是告诉自动布局: “按比例拉伸排列的子视图的宽度!”

You then add a label as an arranged subview, and you set this property on the label:然后添加 label 作为排列的子视图,并在 label 上设置此属性:

setContentHuggingPriority(.required, for: .horizontal)

So you just told auto-layout: "Do NOT stretch the width of this label!"所以你只是告诉自动布局: 不要拉伸这个标签的宽度!”

Kinda tough for auto-layout to both stretch and not stretch the view at the same time:)自动布局很难同时拉伸不拉伸视图:)

Unless you know exactly why you want .fillProportionally (and in this case, that is not what you want), don't use it.除非您确切知道为什么要.fillProportionally (在这种情况下,这不是您想要的),否则不要使用它。 For your layout, you want the default .fill .对于您的布局,您需要默认的.fill

So, if we forget for a moment that you are loading ChildVC as a, well, child VC ( grin ) and set ChildVC as the "root" view controller, and leave sv.distribution =.fillProportionally , you'll get layout errors.因此,如果我们暂时忘记了您将ChildVC作为子 VC ( grin ) 加载并将ChildVC设置为“根”视图 controller 并离开sv.distribution =.fillProportionally ,您将收到布局错误。

If you change that to sv.distribution =.fill , you won't get layout errors.如果将其更改为sv.distribution =.fill则不会出现布局错误。

But, back to using that VC as a child ... even with .fill you'll still get layout errors.但是,回到使用那个 VC 作为一个孩子......即使使用.fill你仍然会得到布局错误。 So...所以...

Change your "load the child" code in ParentVC to this:ParentVC中的“加载孩子”代码更改为:

class ParentVC: UIViewController {
    
    override func viewDidLoad() {
        
        let vcContainer = UIView()
        view.addSubview(vcContainer)
        vcContainer.backgroundColor = .systemYellow
        vcContainer.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            vcContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
            vcContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -150),
            vcContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
            vcContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50),
        ])
        
        let vc = ChildVC()
        addChild(vc)
        vcContainer.addSubview(vc.view)
        
        vc.view.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            vc.view.topAnchor.constraint(equalTo: vcContainer.topAnchor),
            vc.view.leadingAnchor.constraint(equalTo: vcContainer.leadingAnchor),
            vc.view.trailingAnchor.constraint(equalTo: vcContainer.trailingAnchor),
            vc.view.bottomAnchor.constraint(equalTo: vcContainer.bottomAnchor),
        ])
        
        vc.didMove(toParent: self)
    }
    
}

That approach, combined with sv.distribution =.fill , gets rid of the errors.这种方法与sv.distribution =.fill结合使用,可以消除错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么单视图的UIStackView,按比例填充,布局边距会导致模糊约束错误? - Why does a UIStackView with a single view, fill Proportionally, and Layout Margins causes ambiguous constraint error? 如何在 Xcode 的嵌入式堆栈视图中设置边距而不会出现约束错误? - How do I set margins in an embedded Stack View in Xcode without getting constraint errors? 如何解决UIStackView约束问题 - How to fix UIStackView constraint issue 当设备旋转后按比例填充和水平轴时,带有表情符号字符的UIStackView的标签无法正确呈现 - UIStackView's labels with emoji characters are not rendered properly when filled proportionally and horizontal axis after device rotates UIStackView 布局边距内的 UITableView - UITableView inside UIStackView layout margins UIStackView内的UITextField间距关于宽度约束的问题 - UITextField inside UIStackView Spacing Issue on width constraint 如何指定间距约束作为超级视图尺寸的一部分? - How do I specify a spacing constraint as a proportion of the superview's size? 在9.0之前的iOS版本上模仿UIStackView`填充比例&#39;布局方法 - Mimic UIStackView `fill proportionally` layout approach on iOS version prior to 9.0 有什么办法可以改变UIStackView中的UITextView的行距/边距/填充? - Is there any way to alter line spacing/margins/padding for a UITextView inside a UIStackView? 在UIStackView中按比例填写 - Fill Proportionally in UIStackView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM