allenlinli
allenlinli

Reputation: 2154

How do I layout view which is on storyboard programmatically?

I try to use auto layout programmatically by visual format language on a view which is on storyboard but failed. The code is as below: (Btw, the storyboard which shows bView is not important, so I didn't upload storyboard's picture. And I didn't setup any constrain on storyboard.)

class ViewController: UIViewController {

    @IBOutlet var bView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        bView.translatesAutoresizingMaskIntoConstraints = false
        var allConstraints = [NSLayoutConstraint]()
        let vC =  NSLayoutConstraint.constraintsWithVisualFormat("V:|-[bView]-|", options: [], metrics: nil, views: ["bView":bView])
        let hC = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[bView]-|", options: [], metrics: nil, views: ["bView":bView])
        allConstraints += vC
        allConstraints += hC
        NSLayoutConstraint.activateConstraints(allConstraints)
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
    }
}

But when it executes, it shows error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse constraint format: Unable to interpret '|' character, because the related view doesn't have a superview V:|-[bView]-| ^'

I guess maybe the superView (the view of the viewController) did add on the mainWindow. So I tried to fix this problem by moving the code to viewWillLayoutSubviews(). As Below:

class ViewController: UIViewController {

    @IBOutlet var bView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        bView.translatesAutoresizingMaskIntoConstraints = false
        var allConstraints = [NSLayoutConstraint]()
        let vC =  NSLayoutConstraint.constraintsWithVisualFormat("V:|-[bView]-|", options: [], metrics: nil, views: ["bView":bView])
        let hC = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[bView]-|", options: [], metrics: nil, views: ["bView":bView])
        allConstraints += vC
        allConstraints += hC
        NSLayoutConstraint.activateConstraints(allConstraints)
    }
}

Then it shows a really funny wrong result.

enter image description here

So, how do I layout a view which is on storyboard programmatically?


What's more, there's a funny result like this: (It's not related to the question directly, but you can try it for fun!)

enter image description here

With code:

class ViewController: UIViewController {

    @IBOutlet var bView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        bView.translatesAutoresizingMaskIntoConstraints = false
    }
}

Upvotes: 1

Views: 524

Answers (1)

vacawama
vacawama

Reputation: 154641

If you are trying to constrain the blue rectangle, then your first problem is that your bView outlet is incorrectly wired to your top level view (the white background). Delete that connection in the Connections Inspector and then wire the blue view to bView.

If you add a view in Interface Builder, but don't give it any constraints, then Xcode will add 4 constraints at build time. If you click on your view, you will see the following message in the Size Inspector:

The selected views have no constraints. At build time, explicit left, top, width, and height constraints will be generated for the view.

So, your view is already fully specified. If you add any more constraints in code you will have conflicts.

So, how can you add constraints in code for a view laid out in the Storyboard? You need to do the following:

  1. Add explicit constraints in the Storyboard for left, top, width, and height.

    enter image description here

  2. Edit these 4 constraints in the Size Inspector and check the box next to Placeholder [] Remove at build time.

    add 4 explicit constraints

Then, these 4 constraints will be removed at build time leaving the view without constraints. Now your code is free to add constraints.

Upvotes: 1

Related Questions