Core Layout Runtime
In addition to the “display” pass Cocoa has always used, Cocoa Auto Layout adds two more passes that occur when rendering a window: updateConstraintsIfNeeded and layoutIfNeeded. These occur in order: update constraints, layout, display. If you invoke display manually, it invokes layout and layout invokes updateConstraints.
You can think of the update constraints pass as a measurement pass that communicates changes in geometry to the layout system. For example, if you change the title of a button at some point the text has to be measured, and a constraint has to be set up that communicates that information into the layout system. The update constraints pass is bottom-up.
It is in the layout pass that the frames of views are updated. The layout pass is top-down.
These passes have parallel sets of methods:
Display | Layout | Update Constraints | Override | Invoke Directly | |
|---|---|---|---|---|---|
Perform pass at window level |
( |
( |
( | No. | Normally called automatically by AppKit, but may be called if you need things to be up-to-date right now. |
Perform pass at view level Sets things up and invokes the view overridable method on all views in subtree that are dirty with respect to the pass. |
( |
( |
( | No. | Normally called automatically by AppKit, but may be called if you need things to be up-to-date right now. |
View level overridable method Subclassers should override this method to do the requested work for the receiver. This implementation should not dirty the current or previous passes or invoke later passes. |
( |
( |
( | Yes. | You should not call these methods directly. |
Invalidation Get / set methods for invalidation of the pass. |
|
|
(
( | No. | Yes, if/when necessary. |
If you’re implementing a custom view, the most common methods to interact with are the view-level overridable methods and the invalidation methods.
You can override
updateConstraintsto perform deferred constraint setup. You invokesetNeedsUpdateConstraints:when you have set up you want to defer. This is particularly useful when a nib file is loaded and properties are changing a lot—you won’t receiveupdateConstraintsuntil things have settled down.You should only override
layoutonly if you want to do custom layout. If you do, then you also need to invokesetNeedsLayout:when something that feeds into your custom layout changes.
To reiterate: you never need to call setNeedsLayout: unless you override layout. Based on changes to constraints, the layout engine determines when layout is required.
A controller object is typically more concerned with the NSWindow and NSView methods that perform the pass. These uses are more rare, though still valid and needed on occasion.
Perform the update constraints pass manually to make sure all constraints are up to date.
You might do this before introspecting a constraint to extract a metric.
Perform the layout pass manually if you want to extract frames from views and make decisions based on them. If you don’t make sure layout is up to date first, the frames won’t be meaningful.
An
NSAlertobject uses this as part of its layout. The constraint-based system doesn’t deal with flowed text and line breaking any better (or worse) than springs and struts does.NSAlertsets up all its constraints except for anything giving the height of the text fields. Then it callslayoutSubtreeIfNeeded. At this point the text fields have the correct width but not the correct height. It then usesNSTextFieldmethods to find the appropriate height for the fields given their width, and adds the height constraints.
© 2012 Apple Inc. All Rights Reserved. (Last updated: 2012-09-19)