• 0
Votes
name
name Punditsdkoslkdosdkoskdo

How to add constraints programmatically using Swift

I'm trying to figure this out since last week without going any step further. Ok, so I need to apply some constraints programmatically in Swift to a UIView using this code:

var new_view:UIView! = UIView(frame: CGRectMake(0, 0, 100, 100));
new_view.backgroundColor = UIColor.redColor();
view.addSubview(new_view);

var constX:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0);
self.view.addConstraint(constX);

var constY:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0);
self.view.addConstraint(constY);

var constW:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0);
self.view.addConstraint(constW);

var constH:NSLayoutConstraint = NSLayoutConstraint(item: new_view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: new_view, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0);
self.view.addConstraint(constH);

But Xcode returns this weird output:

2014-10-03 09:48:12.657 Test[35088:2454916] 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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
"<NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea4516c0 h=--& v=--& UIView:0x7fa4ea429290.midX == + 50>",
"<NSLayoutConstraint:0x7fa4ea452830 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fa4ea4470f0(375)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea446db0 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' H:|-(0)-[UIView:0x7fa4ea4470f0]   (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea446830 UIView:0x7fa4ea429290.centerX == UIView:0x7fa4ea4470f0.centerX>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in
<UIKit/UIView.h> may also be helpful.

2014-10-03 09:48:12.658 Test[35088:2454916] 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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea451b30 h=--& v=--& UIView:0x7fa4ea429290.midY == + 50>",
"<NSLayoutConstraint:0x7fa4ea44cf00 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7fa4ea4470f0(667)]>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa4ea452700 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' V:|-(0)-[UIView:0x7fa4ea4470f0]  (Names: '|':UIWindow:0x7fa4ea444b20 )>"
)

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fa4ea44d160 UIView:0x7fa4ea429290.centerY == UIView:0x7fa4ea4470f0.centerY>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

Can you help me? Thanks a lot

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 4 / iOS 11):


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: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
    let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.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: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
    let heightConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.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: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.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: NSLayoutFormatOptions.alignAllCenterY, metrics: nil, views: views)
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutFormatOptions.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: NSLayoutFormatOptions.alignAllCenterY, metrics: nil, views: views)
    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-(<=0)-[newView(100)]", options: NSLayoutFormatOptions.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: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.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: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.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: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    let heightConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[newView(100)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)
    NSLayoutConstraint.activate(widthConstraints)
    NSLayoutConstraint.activate(heightConstraints)
    NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
    NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
}

4. Using UIViewAutoresizing

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 = [UIViewAutoresizing.flexibleLeftMargin, UIViewAutoresizing.flexibleRightMargin, UIViewAutoresizing.flexibleTopMargin, UIViewAutoresizing.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 UIKit

class 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])
    }

}
  • 0
Reply Report