orange_juice orange_juice - 3 months ago 26
Swift Question

Setting constraints on a list of UILabels

I'm trying to create a vertical list of UILabels by using anchors as constraints, but for some reason the UILabels don't show in the simulator. This is what I'm doing:

let propertyNameLabel = UILabel();
propertyNameLabel.frame = CGRectMake(0,0, 100, 100);
propertyNameLabel.text = propertyName;
propertyNameLabel.textColor = UIColor.whiteColor();
propertyNameLabel.textAlignment = .Center;
self.addSubview(propertyNameLabel);


var last_anchor = propertyNameLabel.bottomAnchor;

for variable in variableList
{
let propertyNameLabel_temp = UILabel();
propertyNameLabel_temp.text = variable;

propertyNameLabel_temp.textColor = UIColor.whiteColor();
propertyNameLabel_temp.translatesAutoresizingMaskIntoConstraints = false;
self.addSubview(propertyNameLabel_temp);

propertyNameLabel_temp.topAnchor.constraintEqualToAnchor(last_anchor, constant: 10)
propertyNameLabel_temp.bottomAnchor.constraintEqualToAnchor(last_anchor, constant: 50)

propertyNameLabel_temp.widthAnchor.constraintEqualToAnchor(self.widthAnchor);

last_anchor = propertyNameLabel_temp.bottomAnchor;

}


Where variabeList is just a list of variables. The only UILabel that shows is the one that I declare explicitly at the top (propertyNameLabel). Where am I going wrong?

Answer

Your code is full of mistakes. You cannot use the frame for propertyNameLabel and constraints for the other labels. Your label constraints never give the labels a horizontal position of any kind.

Think of a view as having four features: x-position, y-position, height, and width. Your constraints must unambiguously determine all four of those for all your views that are involved in autolayout! Otherwise, you will see nothing.

Cocoa provides methods that you can call to learn whether your constraints have ambiguous (insufficient layout). You can also use View Debugging. Use the tools provided! Do not guess.

Here is actual code that creates a column of labels (in a superview sv). Look at how much has to be specified for this to work!

    var con = [NSLayoutConstraint]()
    con.appendContentsOf(
        NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|[sv]|",
            options:[], metrics:nil,
            views:["sv":sv]))
    con.appendContentsOf(
        NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|[sv]|",
            options:[], metrics:nil,
            views:["sv":sv]))
    var previousLab : UILabel? = nil
    for i in 0 ..< 30 {
        let lab = UILabel()
        // lab.backgroundColor = UIColor.redColor()
        lab.translatesAutoresizingMaskIntoConstraints = false
        lab.text = "This is label \(i+1)"
        sv.addSubview(lab)
        con.appendContentsOf(
            NSLayoutConstraint.constraintsWithVisualFormat(
                "H:|-(10)-[lab]",
                options:[], metrics:nil,
                views:["lab":lab]))
        if previousLab == nil { // first one, pin to top
            con.appendContentsOf(
                NSLayoutConstraint.constraintsWithVisualFormat(
                    "V:|-(10)-[lab]",
                    options:[], metrics:nil,
                    views:["lab":lab]))
        } else { // all others, pin to previous
            con.appendContentsOf(
                NSLayoutConstraint.constraintsWithVisualFormat(
                    "V:[prev]-(10)-[lab]",
                    options:[], metrics:nil,
                    views:["lab":lab, "prev":previousLab!]))
        }
        previousLab = lab
    }