Nick
Nick

Reputation: 4248

Where are constraints updated for size classes?

I have a constraint in interface builder with a default value and a compact width value. I have this constraint linked to an IBOutlet so I can get the constant value in code at runtime. If I run on an iPhone 4S simulator, in viewDidLoad the constant is the default value. Neither willTransitionToTraitCollection or viewWillTransitionToSize get called, but at some point the constraint is updated to the compact value as later on it is correct. Where does the constraint get updated by UIViewController? It's not updateViewConstraints.

Update: The suggested viewDidLayoutSubviews and traitCollectionDidChange methods are not where the constant is changed either:

override func viewDidLayoutSubviews() {
    println("Before viewDidLayoutSubviews: \(self.navControllerBottomSpaceConstraint.constant)")
    super.viewDidLayoutSubviews()
    println("After viewDidLayoutSubviews: \(self.navControllerBottomSpaceConstraint.constant)")
}

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    println("Before traitCollectionDidChange: \(self.navControllerBottomSpaceConstraint.constant)")
    super.traitCollectionDidChange(previousTraitCollection)
    println("After traitCollectionDidChange: \(self.navControllerBottomSpaceConstraint.constant)")
}

Output:

Before viewDidLayoutSubviews: 20.0
After viewDidLayoutSubviews: 20.0
Before viewDidLayoutSubviews: 20.0
After viewDidLayoutSubviews: 20.0
Before viewDidLayoutSubviews: 20.0
After viewDidLayoutSubviews: 20.0
Before viewDidLayoutSubviews: 20.0
After viewDidLayoutSubviews: 20.0
Before traitCollectionDidChange: 20.0
After traitCollectionDidChange: 20.0
Before viewDidLayoutSubviews: 0.0
After viewDidLayoutSubviews: 0.0
Before viewDidLayoutSubviews: 0.0
After viewDidLayoutSubviews: 0.0

Upvotes: 1

Views: 513

Answers (2)

Nick
Nick

Reputation: 4248

Thanks to Matt and Sega-Zero for pointing me in the right direction.

The answer is the constraint is updated in the view's first layoutSubviews after it has entered the view hierarchy. So in your view controller you can do this:

override func viewDidLayoutSubviews() {
    if self.propertyCalculatedFromConstraints == nil && self.view.window != nil {
        // constraints and sizes are now valid
        self.propertyCalculatedFromConstraints = self.constraint.constant
    }
    super.viewDidLayoutSubviews()
}

override func viewDidDisappear() {
    self.propertyCalculatedFromConstraints = nil
    super.viewDidDisappear()
}

Upvotes: 1

Sega-Zero
Sega-Zero

Reputation: 3017

traitCollectionDidChange: is the place where you can catch size classes change or viewDidLayoutSubviews of the parent view is the place where you can detect any autolayout changes

Upvotes: 0

Related Questions