Yonny
Yonny

Reputation: 402

Determining width of a UIView using autolayout - SWIFT

Alright so in the interface builder (Main.storyboard), I have a containerView:UIView embedded in a UIScrollView. Within in the containerView I want to create additional UIView's to hold blocks of content such as a header, body, etc. The reason for doing it like this, is so that the content can scroll vertically but not horizontally.

My goal is to use autolayout to create these different UIView's. As of right now the containerView automatically adjusts it's width depending on the screen size of the device being used, as to prevent horizontal scrolling. It does this using an IBOutlet I created for the width constraint. It currently looks like so:

@IBOutlet var containerView: UIView!
@IBOutlet var containerViewWidthConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    super.viewDidLoad()

    //Prevents horizontal scrolling
    containerViewWidthConstraint.constant = self.view.frame.size.width

    createHeader()
}

Then I created a function called createheader{} which pins a headerView:UIView at the top of the containerView, and 8 points from either edge of the containerView:

func createHeader() {
    //Create header
    let headerView = UIView()
    headerView.backgroundColor = UIColor.blueColor()
    self.containerView.addSubview(headerView)

    //Create header constraints
    let leftMargin = NSLayoutConstraint(item: headerView, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1.0, constant: 8)
    let rightMargin = NSLayoutConstraint(item: containerView, attribute: .Trailing, relatedBy: .Equal, toItem: headerView, attribute: .Trailing, multiplier: 1.0, constant: 8)
    let topMargin = NSLayoutConstraint(item: headerView, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1.0, constant: 70)
    let heightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 160)

    //Activate header constraints
    headerView.setTranslatesAutoresizingMaskIntoConstraints(false)
    NSLayoutConstraint.activateConstraints([leftMargin,rightMargin,topMargin,heightConstraint])

    println(headerView.frame.size.width)
}

Now since the size of the content inside the headerView will be dependent on the screen size of the device being used, I want to be able to create functions that size the width of the content depending on the size of the width of the headerView itself. However every time I try to grab the width of the headerView using:

println(headerView.frame.size.width)

It returns a value of zero, which is obviously not the case because it is still creating a blue-background headerView according to the constraints above.

Why is SWIFT not recognizing that the headerView has a width? And how can I grab the width of the headerView?

Upvotes: 2

Views: 3251

Answers (1)

hennes
hennes

Reputation: 9342

After installing constraints you need to call layoutIfNeeded if you want to update the frames immediately.

func createHeader() {
    //Create header
    let headerView = UIView()
    headerView.backgroundColor = UIColor.blueColor()
    self.containerView.addSubview(headerView)

    ...

    //Activate header constraints
    headerView.setTranslatesAutoresizingMaskIntoConstraints(false)
    NSLayoutConstraint.activateConstraints([leftMargin,rightMargin,topMargin,heightConstraint])

    self.containerView.layoutIfNeeded() // Updates the frames
    println(headerView.frame.size.width) // Will output the correct width
}

Note that this will happen automatically on the next iteration of the UI loop which is, however, not helpful to you when you want to see the effects immediately.

Upvotes: 3

Related Questions