In an constraint-based layout system, the ability to debug effectively is clearly very important. Cocoa Auto Layout offers several features to help you find the source of errors.
An exception is thrown if you configure constraints that cannot be satisfied.
Auto Layout provides runtime support for visualizing constraints.
Visualization may be useful both for finding a problematic constraint, and for detecting ambiguous constraints.
You can programmatically query the system to ask about ambiguous constraints.
You can send a view a
hasAmbiguousLayoutmessage to determine whether its frame is ambiguous, and visualize the ambiguity using
exerciseAmbiguityInLayout(see “Handling Ambiguity”).
An instrument in Instruments helps you to understand changes over time.
The Auto Layout instrument may be included with the developer tools in the future, but is currently provided as sample code in a template—see Cocoa Autolayout Demos.
Broadly speaking, there are two phases to debugging a layout problem:
Map from “this view is in the wrong place” to “this constraint (or these constraints) is (are) incorrect.”
Map from “this constraint is incorrect” to “this code is incorrect.”
Identify the view with an incorrect frame.
It may be obvious which view has the problem; if it is not, you may find it helpful to use the
_subtreeDescriptionto create a textual description of the view hierarchy. (The
_subtreeDescriptionmethod is not public API; it is, however, permissible to use for debugging purposes.)
If possible, reproduce the issue while running under the Auto Layout template in Instruments.
(The Auto Layout instrument may be included with the developer tools in the future, but is currently provided as sample code in a template—see Cocoa Autolayout Demos).
Find the bad constraint or constraints.
To get the constraints affecting a particular view, use
constraintsAffectingLayoutForOrientation:. You can then inspect the constraints in the debugger. They are printed using the visual format notation. If your views have identifiers (see
NSView)), they print out using the identifier in the description, like this:
<NSLayoutConstraint: 0x400bef8e0 H:[refreshSegmentedControl]-(8)-[selectViewSegmentedControl] (Names: refreshSegmentedControl:0x40048a600, selectViewSegmentedControl:0x400487cc0 ) >
otherwise the output looks like this:
<NSLayoutConstraint: 0x400cbf1c0 H:[NSSegmentedControl:0x40048a600]-(8)-[NSSegmentedControl:0x400487cc0]>
If it’s not obvious which constraint is wrong at this point, visualize the constraints on screen by passing the constraints to the window using
Here’s an example of visualizing the constraints affecting the find field’s horizontal layout:
When you click a constraint, it is printed in the console. In this way you can you can determine which is which, and typically identify which is incorrect.
At this point you may be informed that the layout is ambiguous (see “Handling Ambiguity”).
Find the code that’s wrong.
Sometimes, once you have identified the incorrect constraint, you will know what to do to fix it.
If this is not the case then, in Instruments, search for the pointer of the constraint (or some of its description). This will show you interesting events in that constraint’s lifecycle—its creation, modification, installation into windows, and so on. For each of these you can see the backtrace where it happened. Find the stage at which things went awry, and look at the backtrace. This is the code with the problem.
In the above workflow, we assumed that the issue was an incorrect constraint. It is also possible that the problem is due to a missing constraint. A layout is ambiguous if it is underspecified. For example, suppose the system consists of one constraint.
x + y == 100
Because there are an infinite number of solutions to this equation, the system is ambiguous (as opposed to unsatisfiable). You can resolve it by adding a second constraint such as:
x == y
In the normal course of solving layout, the system detects unsatisfiability but not ambiguity. (It is a computationally expensive task to detect ambiguity in this system.) However, if you visualize constraints the system does check for ambiguity. If it detects an ambiguity, the visualizer presents an Exercise Ambiguity button. Figure 4-1 shows the find panel after one of the constraints has been removed.
Exercising ambiguity (clicking the button) makes your UI toggle between different states it could be in given the current set of constraints. Figure 4-2 shows the layout of the find panel after clicking Exercise Ambiguity. Notice the different layout.
© 2012 Apple Inc. All Rights Reserved. (Last updated: 2012-09-19)