Search code examples
iosswiftautolayoutvisual-format-language

Swift: programmatically adding a field in a position relative to the bottom of the view


I want to do this programmatically without Interface Builder. I want to add a UITextField to my iOS app a constant distance from the bottom of the app view. I've looked at a lot of existing questions and answers. None are in Swift and this topic seems relatively undocumented.


Solution

  • There are several somewhat related answers out there, but here are all the pieces it took to get this working:

    1) I needed to create a constraint like

    let bottomConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[inputBox]-50-|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox])[0] as! NSLayoutConstraint
    

    This uses Swift's domain specific language "visual format language" (VFL): V:[inputBox]-50-|, where the 'V' means vertical, 50 is a number of pixels and the '|' refers to the bottom of the parent view.

    2) The UITextField had to be added to the view before adding the constraint to the view so '|' above could find the parent view.

    3) Once I used one NSLayoutConstraint I had to use them for all aspects of sizing and positioning for this element. Hence I had to add these two lines to describe its width and height:

    let heightConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[inputBox(==70)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox])[0] as! NSLayoutConstraint
    let widthConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:[inputBox(==superview)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox, "superview":self.view])[0] as! NSLayoutConstraint
    

    4) To get my UITextField to interact correctly with VFL I had to add this line:

    inputBox.setTranslatesAutoresizingMaskIntoConstraints(false)
    

    Putting it all together:

    let inputBox = UITextField(frame: rect)
    inputBox.backgroundColor = UIColor.yellowColor()
    inputBox.setTranslatesAutoresizingMaskIntoConstraints(false)
    self.view.addSubview(inputBox)
    
    let bottomConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[inputBox]-50-|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox])[0] as! NSLayoutConstraint
    let heightConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:[inputBox(==70)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox])[0] as! NSLayoutConstraint
    let widthConstraint : NSLayoutConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:[inputBox(==superview)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["inputBox": inputBox, "superview":self.view])[0] as! NSLayoutConstraint
    
    view.addConstraint(bottomConstraint)
    view.addConstraint(heightConstraint)
    view.addConstraint(widthConstraint)