Swift以编程方式添加的约束不起作用

Swift以编程方式添加的约束不起作用,swift,uikit,constraints,programmatically-created,Swift,Uikit,Constraints,Programmatically Created,我在滚动视图中有一个视图: 现在我想以编程方式将子视图添加到该视图中。这就是我的代码: 子视图(工作) 现在我重复执行此代码: private func makeTextLabel(text: NSAttributedString, bgColor: UIColor?, maxWidth: CGFloat?) -> UILabel { //Creates label let label = UILabel() label.translatesAutoresizi

我在滚动视图中有一个视图:

现在我想以编程方式将子视图添加到该视图中。这就是我的代码:

  • 子视图(工作)

  • 现在我重复执行此代码:

    private func makeTextLabel(text: NSAttributedString, bgColor: UIColor?, maxWidth: CGFloat?) -> UILabel {
        //Creates label
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        lv.addSubview(label)
        //Adjustments
        if(bgColor != nil) {
            label.backgroundColor = bgColor
        }
        label.textColor = UIColor.black
        label.attributedText = text
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        let width = maxWidth ?? lv.frame.size.width-8
        label.widthAnchor.constraint(equalToConstant: width).isActive = true
        label.heightAnchor.constraint(equalToConstant: heightForLabel(attributedText: label.attributedText, width: width)).isActive = true
        label.leadingAnchor.constraint(equalTo: lv.leadingAnchor, constant: 4).isActive = true
        let previousView = lv.subviews[lv.subviews.count-1]
        label.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant:  10).isActive = true
        return label
    }
    
    所有标签都已添加,但约束根本不起作用。下面是它的样子(当我执行上述方法2次时):

    编辑:主要问题已解决。我正在使用堆栈视图。()

    现在,我希望标签与边之间有偏移,因此我使用这些线:

        label.leadingAnchor.constraint(equalTo: lessonStackView.leadingAnchor, constant: offset).isActive = true
        label.trailingAnchor.constraint(equalTo: lessonStackView.trailingAnchor, constant: -offset).isActive = true
    
    但由于StackView似乎自己设置了x约束,我得到了以下警告:

    无法同时满足约束。 可能下面列表中至少有一个约束是您不想要的。 试试这个: (1) 看看每一个约束,试着找出你不期望的; (2) 找到添加了不需要的约束的代码,然后修复它。 ( “UILabel:0x7f9c16c22c30'Falls dir die应用程序gef\U00e4llt…”(活动,名称:“|”):JavaProf.MultipleContentsView:0x7f9c19024a60)>, "", "" )

    将尝试通过打破约束进行恢复


    如何解决此问题?

    删除
    width
    锚定。您不应该关心宽度(而且您并不真正了解宽度),而是使用
    trailingAnchor

    label.trailingAnchor.constraint(equalTo: lv.trailingAnchor, constant: -4).isActive = true
    
    删除高度锚定,让系统为您计算高度:

    label.setContentHuggingPriority(.required, for: .vertical)
    label.setContentCompressionResistancePriority(.required, for: .vertical)
    
    这应该是所有需要的


    但是,作为旁注,如果要对标签堆栈(或其他视图)使用
    UIStackView
    ,并且希望它们具有不同的前导间距,则可以使用
    UIStackView
    ,而不是对上一个标签创建约束,您可以使用
    UIStackView

    1) 将标签嵌入
    ui视图
    。让
    UIView
    填充堆栈视图的宽度,并为视图提供包含的标签约束

    2) 将堆栈视图
    Aligment
    设置为
    Trailing
    。然后向每个标签添加宽度约束,该约束等于堆栈视图的宽度。对于希望具有32点“左边距”的标签,请将该标签上的常数设置为
    -32

    下面是一个简单的例子:

    class LeftMarginViewController: UIViewController {
        let stackView: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.alignment = .trailing
            v.distribution = .fill
            v.spacing = 8
            return v
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            for i in 1...7 {
                let v = UILabel()
                v.backgroundColor = .yellow
                v.numberOfLines = 0
                if i == 5 {
                    v.text = "Label 5 has a lot of text to demonstrate what happens when it needs to wrap onto multiple lines."
                } else {
                    v.text = "Label \(i)"
                }
                stackView.addArrangedSubview(v)
                switch i {
                case 6:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: -32.0).isActive = true
                case 2, 4, 5:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: -16.0).isActive = true
                default:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: 0.0).isActive = true
                }
            }
    
            stackView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(stackView)
    
            let g = view.safeAreaLayoutGuide
    
            NSLayoutConstraint.activate([
                stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
                stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
                stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
            ])
    
        }
    }
    
    堆栈视图具有
    对齐:尾部
    ,每个标签的宽度等于堆栈视图的宽度,标签2、4和5具有
    常量=-16
    ,标签6具有
    常量=-32

    结果:


    我现在正在使用StackView。我更新了我的问题,如果你再看一眼就好了!如果要从边偏移,只需偏移整个堆栈视图。这是最简单的方法。谢谢,但是偏移量取决于不同的标签,所以在这种情况下我不能这样做。谢谢你的回答。我没有完全使用这种方法,但我将StackView的对齐方式改为居中,而不是填充。现在警告消失了,一切正常
    class LeftMarginViewController: UIViewController {
        let stackView: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.alignment = .trailing
            v.distribution = .fill
            v.spacing = 8
            return v
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            for i in 1...7 {
                let v = UILabel()
                v.backgroundColor = .yellow
                v.numberOfLines = 0
                if i == 5 {
                    v.text = "Label 5 has a lot of text to demonstrate what happens when it needs to wrap onto multiple lines."
                } else {
                    v.text = "Label \(i)"
                }
                stackView.addArrangedSubview(v)
                switch i {
                case 6:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: -32.0).isActive = true
                case 2, 4, 5:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: -16.0).isActive = true
                default:
                    v.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0, constant: 0.0).isActive = true
                }
            }
    
            stackView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(stackView)
    
            let g = view.safeAreaLayoutGuide
    
            NSLayoutConstraint.activate([
                stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
                stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
                stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
            ])
    
        }
    }