8

I'm having some issues of figuring out when the auto-contraints setup on a XIB are applied in the view setup process.

For more explanation:

  • I've setup a XIB for a view
  • I set the "Simulated Metrics" Size to iPhone 3.5-Inch
  • I've added auto-constraints to the subviews inside this view
  • In the View Controller I perform certain operations dependent on the subview (IBOutlet) frames/bounds in the viewDidLoad method
  • In the View I perform certain operations dependent on the subview (IBOutlet) frames/bounds in the awakeFromNib method

In those 2 methods (ViewController::viewDidLoad and View::awakeFromNib) the IBOutlet views HAVE been loaded but the constraints have no yet been applied. The actual frame is still set to the iPhone 3.5" size (width 320) when using a larger simulator (such as the iPhone 6 simulator).

When are these auto-constraints applied and when should any necessary operations that would need the ACTUAL frame/bounds of the subviews take place?

I'm using XCode 6.3, Swift (1.2)

pkearney06
  • 113
  • 1
  • 4

3 Answers3

13

The constraints are applied in the layoutSubviews method. So if you want to do something after they are applied in a UIView subclass, override the method:

   override func layoutSubviews() {
    super.layoutSubviews()
    //the frames have now their final values, after applying constraints
  }

In a UIViewController subclass, use viewDidLayoutSubviews for the same purpose:

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    //the frames have now their final values, after applying constraints
  }

Please note that you shouldn't set frame / bounds for a view if you added auto layout constraints to this view.

Michał Ciuba
  • 7,876
  • 2
  • 33
  • 59
  • 1
    While working with a custom UITableViewCell subclass, this alone didn't update the frames immediately; only scrolling away from a cell and again caused it to be laid out. Adding `setNeedsLayout(); layoutIfNeeded` at the end of my `updateConstraints` override seems to have fixed it. Surprisingly, replacing `layoutIfNeeded` with `layout` did not work, not even after `setNeedsLayout`. – Phlippie Bosman Dec 01 '17 at 16:31
0

Note for Xcode 8: If you use auto layout, you may have a problem with new feature: view as [any device]. When you test your app on another device(simulator) and have inferred screen, screen bounds for this device gonna be applied in viewWillLayoutSubviews.

0

you can use method

override func layoutSubviews() {
super.layoutSubviews()
//the frames have now their final values, after applying constraints

}

But this method will be called multiple times in a view's life cycle, such as orientation change or moving in and out views, so you need to handle this.