How to add constraints programmatically using Swift
Do you plan to have a squared UIView
of width: 100 and Height: 100 centered inside the UIView
of an UIViewController
? If so, you may try one of the 6 following Auto Layout styles (Swift 5 / iOS 12.2):
1. Using NSLayoutConstraint
initializer
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0) let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0) let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100) let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100) view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0) let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0) let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100) let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true}
2. Using Visual Format Language
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let views = ["view": view!, "newView": newView] let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views) let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views) view.addConstraints(horizontalConstraints) view.addConstraints(verticalConstraints)}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let views = ["view": view!, "newView": newView] let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterY, metrics: nil, views: views) let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutConstraint.FormatOptions.alignAllCenterX, metrics: nil, views: views) NSLayoutConstraint.activate(horizontalConstraints) NSLayoutConstraint.activate(verticalConstraints)}
3. Using a mix of NSLayoutConstraint
initializer and Visual Format Language
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let views = ["newView": newView] let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0) let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0) view.addConstraints(widthConstraints) view.addConstraints(heightConstraints) view.addConstraints([horizontalConstraint, verticalConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let views = ["newView": newView] let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0) let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0) NSLayoutConstraint.activate(widthConstraints) NSLayoutConstraint.activate(heightConstraints) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let views = ["newView": newView] let widthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views) NSLayoutConstraint.activate(widthConstraints) NSLayoutConstraint.activate(heightConstraints) NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: newView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true}
4. Using UIView.AutoresizingMask
Note: Springs and Struts will be translated into corresponding auto layout constraints at runtime.
override func viewDidLoad() { let newView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = true newView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY) newView.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin, UIView.AutoresizingMask.flexibleRightMargin, UIView.AutoresizingMask.flexibleTopMargin, UIView.AutoresizingMask.flexibleBottomMargin]}
5. Using NSLayoutAnchor
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor) let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor) let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100) let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100) view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor) let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor) let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 100) let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 100) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])}
override func viewDidLoad() { let newView = UIView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true newView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true newView.widthAnchor.constraint(equalToConstant: 100).isActive = true newView.heightAnchor.constraint(equalToConstant: 100).isActive = true}
6. Using intrinsicContentSize
and NSLayoutAnchor
import UIKitclass CustomView: UIView { override var intrinsicContentSize: CGSize { return CGSize(width: 100, height: 100) } }class ViewController: UIViewController { override func viewDidLoad() { let newView = CustomView() newView.backgroundColor = UIColor.red view.addSubview(newView) newView.translatesAutoresizingMaskIntoConstraints = false let horizontalConstraint = newView.centerXAnchor.constraint(equalTo: view.centerXAnchor) let verticalConstraint = newView.centerYAnchor.constraint(equalTo: view.centerYAnchor) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) } }
Result:
It helps me to learn visually, so this is a supplemental answer.
Boilerplate code
override func viewDidLoad() { super.viewDidLoad() let myView = UIView() myView.backgroundColor = UIColor.blue myView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(myView) // Add constraints code here // ...}
Each of the following examples are independent of the others.
Pin left edge
myView.leading = leadingMargin + 20
Method 1: Anchor Style
let margins = view.layoutMarginsGuidemyView.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20).isActive = true
- In addition to
leadingAnchor
, there is alsotrailingAnchor
,topAnchor
, andbottomAnchor
.
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 20.0).isActive = true
- In addition to
.leading
there is also.trailing
,.top
, and.bottom
. - In addition to
.leadingMargin
there is also.trailingMargin
,.topMargin
, and.bottomMargin
.
Set Width and Height
width = 200
height = 100
Method 1: Anchor Style
myView.widthAnchor.constraint(equalToConstant: 200).isActive = truemyView.heightAnchor.constraint(equalToConstant: 100).isActive = true
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = trueNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
Center in container
myView.centerX = centerX
myView.centerY = centerY
Method 1: Anchor Style
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = truemyView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Method 2: NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = trueNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
Notes
- Anchor style is the preferred method over
NSLayoutConstraint
Style, however it is only available from iOS 9, so if you are supporting iOS 8 then you should still useNSLayoutConstraint
Style. - The examples above showed just the one or two constraints that were being focused on. However, in order to properly place
myView
in my test project I needed to have four constraints.
Further Reading
- Programmatically Creating Constraints documentation
If you want to fill your super view then I suggest the swifty way:
view.translatesAutoresizingMaskIntoConstraints = false let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left] NSLayoutConstraint.activate(attributes.map { NSLayoutConstraint(item: view, attribute: $0, relatedBy: .equal, toItem: view.superview, attribute: $0, multiplier: 1, constant: 0) })
Other wise if you need non equal constraints check out NSLayoutAnchor as of iOS 9. Its often much easier to read that using NSLayoutConstraint directly:
view.translatesAutoresizingMaskIntoConstraints = false view.topAnchor.constraint(equalTo: view.superview!.topAnchor).isActive = true view.bottomAnchor.constraint(equalTo: view.superview!.bottomAnchor).isActive = true view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 10).isActive = true view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: 10).isActive = true