5. History
• Display Form Factor Evolution:
• iPhone, iPad, iPhone Retina, iPad Retina, iPhone 4-inch Display !
• Inspired by: Cassowary A Constraint Solving Toolkit
• http://www.cs.washington.edu/research/constraints/cassowary/
• Auto Layout Evolution:
• OS X Lion 10.7 ~ iOS 6.0 ~ Xcode 5
5
6. Old Buzzword: Absolute
• Springs & Struts Approach:
• Set the Frame
• Set the AutoresizingMask
• Springs & Struts Limits:
• Can be applied only between the view and the superview
• Cannot express relationships between two views
• Sometimes needs tweaking code
7. New Buzzword: Dynamic
• Auto Layout loves Dynamism:
• Improved responsiveness to changes in the application
• Auto Layout loves Relationships:
• Codifying the relative way we describe user interfaces
• Auto Layout loves Expressiveness:
• Can specify powerful relationships between views
9. Mathematical Background
• System of Linear Equations: Linear Algebra
{
a₁₁x + a₁₂y = b₁
a₂₁x + a₂₂y = b₂
• System of Linear Equations: Cartesian Plane
{
y = m₁x + c₁
y = m₂x + c₂
13. Constraint Basics
y ☺ mx + c
• y and x are attributes of views:
• left, right, top, bottom, leading, trailing
• width, height, centerX, centerY, baseline
• m and c are floating point values:
• m is the multiplier: the ratio between the attributes
• c is the constant: the size or offset in points
• ☺ is the relation: =, <=, >=
14. Constraint Basics
view.leading >= (superview.leading + 20)
• Constraints are cumulative and do not override each other
• Constraints can cross the view hierarchy
• ↳ but in the same window
• ↳ with some exceptions:
• cannot cross if the hierarchy includes a view that sets the subviews frames manually
• cannot cross if the hierarchy includes a view that have a bounds transform (scrollview)
15. Constraint Priority
@750
@250
nameView
ageView
• Constraints with higher priority levels are satisfied before
constraints with lower priority level
enum {
UILayoutPriorityRequired = 1000,
UILayoutPriorityDefaultHigh = 750,
UILayoutPriorityDefaultLow = 250,
UILayoutPriorityFittingSizeLevel = 50,
};
typedef float UILayoutPriority; // for OS X see NSLayoutPriority
16. Intrinsic Content Size
Follow us @pragmamarkorg
• How large is intrinsically the content of a leaf-level view,
such a button, a label, an imageView, … ?
- (CGSize)intrinsicContentSize {
NSDictionary *attributes = @{
NSFontAttributeName : [UIFont systemFontOfSize:17.0f],
};
return [self.text sizeWithAttributes:attributes];
}
17. Compression Resistance
nameView
ageView
• Which of two views will shrink to fit into this space?
[self.nameView
setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
18. Hugging
nameView
ageView
• Which of two views will expand to fill the space?
[self.nameView
setContentHuggingPriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
19. How Auto Layout Works
{
y = m₁x + c₁
y = m₂x + c₂
• Install constraints on views
• Convert constraints into inequalities
• Solve system of inequalities all at once
• Update views frames
• Display layers on screen
21. Constraints Phase
• From subview to superview
• Trigger via
setNeedsUpdateConstraints
subview
label view
• Add custom view constraints via
updateConstraints
container view
• Prepares each view with the
values it needs to set frames
main view
superview
22. Layout Phase
• From superview to subview
• Can be triggered via
setNeedsLayout
subview
label view
• Force instant-refresh via
layoutIfNeeded
container view
• Applies the frames from the
previous step to each view
main view
superview
23. Display Phase
• From superview to subview
• Can be triggered via
setNeedsDisplay
• Same as Springs & Struts
• drawRect: lives here
subview
label view
container view
main view
superview
31. Add Constraints
• Add Constraints with Control-Drag
• Add Constraints with Align and Pin Menus
• Add Missing or Suggested Constraints
Add Constraints
32. Control-DRAG (or mouse right button)
• Control-Drag from an element to itself, to its container or to
another element
• Auto Layout limits the possibilities of constraints
appropriately, depending on what you drag
• To select multiple constraints at a time hold down the
Command or Shift key
33. Align and Pin Menus
• Align: create alignment constraints:
• Edges, Center and Baseline
• Pin: create spacing constraints:
• Width, Height and Distance from another view
34. Missing or Suggested
• Use Add Missing Constraints to add a non-ambiguous set of
constraints
• Use Reset to Suggested Constraints to remove erroneous
constraints and add a non-ambiguous set of constraints
35. Editing Constraints
• Change the constant, relation and priority of a constraint
• by double-clicking the constraint on the canvas
• by selecting the constraint and using the Attributes inspector
• The type of a constraint cannot be changed
36. Wrong Intermediate States
• Ambiguous Layout: Not enough information { ∞ solutions
• Conflicting Constraints: Too much information { Ø solution
• Misplaced Views: Mismatched position or size
37. Debug & Resolve
• See Xcode Issues Navigator
• Get detailed help using the outline view
• Follow canvas decorations
• Fix constraint via resolving menu
Debug & Resolve
38. Identifying Issues
!
In the Issues
Navigator
!
In the Interface Builder
outline view
On the canvas
Misplaced or ambiguous
constraints are shown in orange,
conflicting constraints are red
39. Ambiguous Layout
• Interface Builder shows ambiguity by drawing frames with
orange borders
• The way you resolve ambiguity depends on the condition
that’s causing it:
• One or More Constraints Are Missing
• Content Size Is Undefined
• The Size of Custom View Content Is Unknown
41. Undefined Content Size
• Some container views depend on the size of their content
• The size is unknown at design time
• You should set placeholder constraints
• This placeholder is removed at build time
Select the constraint !
42. Custom View Unknown
• A Custom View can have a intrinsic content size
• The content size is unknown at design time
• You should set a placeholder intrinsic content size
• The view will not have this intrinsic content size at runtime
Select the view !
43. Conflicting Constraints
• A set of constraints that Auto Layout can’t satisfy
• Conflicting constraints show up on the canvas in red
• To remove all constraints choose:
Issues > Clear Constraints
44. Misplaced Views
• In Interface Builder constraints and frames are separate
• If there is a mismatch you have view misplacement
• Not satisfied constraints show up in orange, with a delta
• A dotted red frame show where the view will be at runtime
45. Misplaced Views
• Choose Issues > Update Frames
• The element moves back to where it was before it was misplaced
• The frames change to satisfy existing constraints
• Choose Issues > Update Constraints
• The constraints are updated to the new location of the element
• The constraints change to match the current frames
51. Visual Format Language
@"H:|[nameView]-20-[ageView]|"
• VFL aka ASCII Art ;-)
• Orientation: V or H
• Superview: | |
• Relation: >=, <=, ==
• Priority:
•[view(<=width@contentHugging)]
•[view(>=width@contentCompressionResistance)]
52. Visual Format Language
• Standard Space: [button1]-[button2]
• Width Constraint: [label(>=50)]
• Connection to Superview: |-50-[centerField]-50-|
• Vertical Layout: V:[topField]-10-[bottomField]
• Flush Views: [leftLabel][rightLabel]
• Priority: [button(100@20)]
• Equal Widths: [button1(==button2)]
• Multiple Predicates: [flexibleButton(>=70,<=100)]
• A Line of Layout: |-[f1]-[f2]-[f3(>=20)]-|
53. Visual Format Language
• The notation prefers good visualization over completeness
• Some constraints cannot be expressed using VFL
• fixed aspect ratio: nameView.width = 3 * nameView.height
• use constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
3*H
H
nameView
54. Installing Constraints
• To make a constraint active, you must add it to a view
• The view that holds the constraint:
• must be an ancestor of the views the constraint involves
• should usually be the closest common ancestor (where a view is an ancestor of itself)
NSArray *constraints = [NSLayoutConstraint
↳ constraintsWithVisualFormat:@"[nameView]-20-[ageView]"
options:0
metrics:nil
views:views];
!
[[self.nameView superview] addConstraints:constraints];
56. Debugging Code
• In lldb shell change the color of a view to find it by memory
(lldb) expr ((UIView *)0x8b24cb0).backgroundColor = [UIColor redColor]
(id) $1 = 0x08c1f190
57. Debugging Code
• In lldb shell log constraints with methods:
• constraints
• constraintsAffectingLayoutForAxis: in iOS |
constraintsAffectingLayoutForOrientation: in OS X
(lldb) po [[self button1] constraints]
Log uses VFL !
<__NSArrayM 0x8d1b980>(
<NSLayoutConstraint:0x8c28620 V:[UIButton:0x8c28df0(30)]>,
<NSLayoutConstraint:0x8c28480 H:[UIButton:0x8c28df0(80)]>,
<NSContentSizeLayoutConstraint:0x8c2f990 H:[UIButton:0x8c28df0(55)] Hug:250 CompressionResistance:750>,
<NSContentSizeLayoutConstraint:0x8c2fab0 V:[UIButton:0x8c28df0(30)] Hug:250 CompressionResistance:750>,
<NSLayoutConstraint:0x8c309b0 UIButtonLabel:0x8c2da00.centerX == UIButton:0x8c28df0.centerX>,
<NSLayoutConstraint:0x8c309f0 UIButtonLabel:0x8c2da00.centerY == UIButton:0x8c28df0.centerY>,
<NSLayoutConstraint:0x8c30a20 UIButtonLabel:0x8c2da00.width <= UIButton:0x8c28df0.width>,
<NSLayoutConstraint:0x8c30a50 UIButtonLabel:0x8c2da00.height <= UIButton:0x8c28df0.height>
)
(lldb) po [[self button1] constraintsAffectingLayoutForAxis:0]
<__NSArrayM 0x8a2e1d0>(
<NSLayoutConstraint:0x8c2c2b0 H:|-(20)-[UIButton:0x8c28df0]
<NSLayoutConstraint:0x8c28480 H:[UIButton:0x8c28df0(80)]>
)
(Names: '|':UIView:0x8c2b1c0 )>,
60. Custom View
• A view can specify its intrinsic content size
• implement method intrinsicContentSize
• return CGSize {NSViewNoInstrinsicMetric, …} to indicate no intrinsic metric for a dimension
• Views must notify auto layout if their intrinsic size changes
• call method invalidateIntrinsicContentSize
• Views indicate baseline offsets
• implement method viewForBaselineLayout (iOS)
• Layout operates on alignment rectangles, not on frames
61. Best Practices
• Add constraints in updateConstraints
• Always call [super updateConstraints]
• Store constraints in strong ivars
• Remove constraints before calling
setNeedsUpdateConstraints
• Don’t remove constraints unnecessarily
• Updating faster than removing/re-adding
62. Animations
y ☺ multiplier * x + constant
[containerView layoutSubtreeIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.nameViewWidthConstraint.constant = finalConstant;
[containerView layoutSubtreeIfNeeded];
}];
• make constraint changes
• don’t animate the frame
• call layoutSubtreeIfNeeded
• change only the constant !
64. Compatibility
• Deployable to previous versions
of OS X (10.7+) and iOS (6+)
• Features requiring Xcode 5
• iOS 7 support
• New Auto Layout workflow
• Readable and diffable XIB
65. Migration Rules
• Start using Auto Layout today for all new User Interfaces
• Use Auto Layout when it makes sense
• Don’t use setFrame:
view.frame = CGRectMake(x, y, width, height);
66. Migration Workflow
• Stop and think
• Don’t try to replicate what the existing code is doing
• Think about the underlying layout
• Try replacing it with nothing!
• Are you working around a limitation of springs and struts?
• Does the code implement a relationship?
• Otherwise, add some constraint
• Prefer adding constraints via Interface Builder
• Think about which component should own each constraint
• Consider centralising it in updateConstraints
• Verify the layout is correct
• Fix issues you may have
67. translatesAutoresizingMaskIntoConstraints
• Views that are aware of Auto Layout can coexist in a window
with views that are not
• If this is value is YES, the view’s superview looks at the
view’s autoresizing mask, produces constraints that
implement it, and adds those constraints to itself
• Set to NO for most views that are aware of Auto Layout
• the constraints generated by translating the autoresizing mask are already sufficient to
completely specify the frame of a view given its superview’s frame
• Too much information can prevent a view from automatically assuming its optimal size
69. Features
• Auto Layout is declarative
• Auto Layout minimizes your calculation
• Auto Layout design is indirect, but it’s also more flexible
• Auto Layout is driven by geometry
• Auto Layout focuses on relationships
• Auto Layout allows and even encourages conflicting rules
• Auto Layout expresses natural content
• Auto Layout seeks optimal solutions
• Auto Layout is distributed
70. Why ?
• Replace Springs & Struts with something better
• Easily handle a variety of display sizes
• Moving view logic back to the view
• Dynamically calculate the user interface
• Prioritise portions of the user interface
• Extend the usefulness of Interface Builder
• Improve layout related code
71. Why Not ?
• A whole new way of thinking about layout
• Steep learning curve when working with code
• Xcode 4 support was frustrating
• Few cases are more difficult to handle
• Spring & Struts has not been deprecated
72. Video References
• WWDC11/103: Cocoa Autolayout
• WWDC12/202: Introduction to Auto Layout for iOS and OS X
• WWDC12/228: Best Practices for Mastering Auto Layout
• WWDC12/232: Auto Layout by Example
• WWDC13/406: Taking Control of Auto Layout in Xcode 5
• NSScreencast #87: Xcode 5 Autolayout Improvements
• NSScreencast #35: Autolayout Fun
• Justin Williams @ 360 iDev 2013
• Cesare Rocchi @ UIKonf 2013
73. Book References
• iOS Developer Library
Auto Layout Guide
• Any new book on iOS 6 | 7
• iOS Auto Layout Demystified
By Erica Sadun
Available: Oct 31, 2013 !