also express geometric relationships between views NSLayoutConstraint foo foo.width = 120 foo foo.width = bar.width bar •Relationships have a coefficient and a constant
also express geometric relationships between views NSLayoutConstraint foo foo.width = 120 foo foo.width = bar.width bar •Relationships have a coefficient and a constant foo.width = bar.width * 2 - 20
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
contributes the constraints it cares about •Layout becomes “owned” Thinking in Constraints Q I’m square! Be centered vertically in me! Be the same height as me!
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
Auto Layout just where you need it ▪ Some compatibility issues to be aware of •A full conversion will pay major dividends Migrating from Springs and Struts
create programmatically [view setTranslatesAutoresizingMaskIntoConstraints:NO] •If you forget, you’ll get unsatisfiable constraint warnings quickly Migrating from Springs and Struts
{… Migrating from Springs and Struts [view setFrame:rect] [view setFrameSize:size] [view setFrameOrigin:point] They all have to go! (But what do I replace them with?)
try to merely 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?
try to merely 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 constraints
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
four properties (two in each dimension) ▪ MinX, Width, MinY, Height ▪ MinX, MaxX, CenterY, MaxY ▪ CenterX, Width, Baseline, Height ▪ etc. •Inequalities by themselves are usually not enough ▪ view.width ≥ 20 – is it 20? 200? 2 billion? ▪ Inequalities don’t care how much larger or smaller you are ▪ But equalities care Ambiguity
still can’t satisfy both •The inequality has a higher priority, so it will be satisfied first •The equality will be satisfied as closely as possible [view(24@500) [view(>=30@525)]
still can’t satisfy both •The inequality has a higher priority, so it will be satisfied first •The equality will be satisfied as closely as possible •No ambiguity! [view(24@500) [view(>=30@525)]
still can’t satisfy both •The inequality has a higher priority, so it will be satisfied first •The equality will be satisfied as closely as possible •No ambiguity! •view.width = 30 [view(24@500) [view(>=30@525)]
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
required constraints can contribute to unsatisfiability ▪ Constraints are required by default! •Sizes are implicitly required to be at least zero Unsatisfiability
Check their -frame •What constraints are making them that size? ▪ Output [view constraintsAffectingLayoutForOrientation/Axis: NSLayoutConstraintOrientationHorizontal/Vertical]
Check their -frame •What constraints are making them that size? ▪ Output [view constraintsAffectingLayoutForOrientation/Axis: NSLayoutConstraintOrientationHorizontal/Vertical] 0 or 1
Check their -frame •What constraints are making them that size? ▪ Output [view constraintsAffectingLayoutForOrientation/Axis: NSLayoutConstraintOrientationHorizontal/Vertical] •Is the layout ambiguous? ▪ Call [view hasAmbiguousLayout] ▪ Call [view exerciseAmbiguityInLayout] 0 or 1
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger. Anatomy of an Unsatisfiability Log
0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger. Anatomy of an Unsatisfiability Log
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
( "<NSLayoutConstraint:0x10441ced0 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX - 11 (Names: LetterView-'H':0x10423c390 )>", "<NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x10441ce70 LetterView-'H'.centerX == LetterPile: 0x102b25230.centerX + 170 (Names: LetterView-'H':0x10423c390 )> Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
of an Unsatisfiability Log View’s identifier Attribute Relation Other View Constant “The letter view’s center should be 11 points to the left of the pile’s center”
syntax when possible H:[NSView:0x102b5b3a0(250)] H:[NSView:0x10480cd00]-(>=50)-[NSView:0x10481e9a0]> “The view’s width is 250” “This view is at least 50 points to the right of that view”
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
constraint based-layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
layout and let CoreAnimation handle animation ▪ Very fast ▪ May transiently appear to violate constraints •Animate constraints directly ▪ Pretty fast ▪ Produces a correct layout at every frame
(readonly) CGFloat multiplier; @property (readwrite) CGFloat constant; @end •The constant may be modified after creation •Permits efficient relayouts •Use an NSTimer •Use the animator proxy constraint.constant += 10 constraint.animator.constant = 10 OS X only
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
per dimension Push Me 120 25 H:[button(>=120] H:[button(<=120] V:[button(>=25)] V:[button(<=25)] •This is sufficient to unambiguously size the view! Compression Resistance Content Hugging
content changes •Auto Layout reestablishes the sizing constraints •If you implement a custom control, call this whenever your intrinsicContentSize might change Short Label Longer L…
content changes •Auto Layout reestablishes the sizing constraints •If you implement a custom control, call this whenever your intrinsicContentSize might change Short Label Longer L… Longer Longer Label
preserve binary compatibility •It may be wrong for the current artwork •intrinsicContentSize can change •Use intrinsicContentSize as a better sizeToFit
preserve binary compatibility •It may be wrong for the current artwork •intrinsicContentSize can change •Use intrinsicContentSize as a better sizeToFit NSRect alignmentRect = (NSRect){NSZeroPoint, [control intrinsicContentSize]}; [control setFrameSize: [control frameForAlignmentRect:alignmentRect].size];
or images ▪ Hard-code values •Do not ▪ Inspect your position, size, or constraints ▪ Call super and “tweak” its value ▪ Use it as a substitute for explicit constraints
Consider using the default implementation ▪ Override - (NS/UIEdgeInsets)alignmentRectInsets; •Do not ▪ Inspect your position, size, or constraints ▪ Call super and “tweak” its value ▪ Use it as a substitute for explicit constraints
the values determined by the constraints NSView -layoutSubviews sets the receiver’s center and bounds to the values determined by the constraints UIView
•Override it to do custom layout as long as you maintain that invariant -layout sets the receiver’s frame to the values determined by the constraints NSView -layoutSubviews sets the receiver’s center and bounds to the values determined by the constraints UIView
constraint-based layouts ▪ Ambiguity ▪ Unsatisfiability ▪ Reading log messages •Unleashing the power of constraints ▪ Animation ▪ Writing a custom control ▪ Internationalization
no) code •Think declaratively •Be wary of ambiguity and unsatisfiability •The log messages are there to help •Judicious overriding lets your custom views integrate with Auto Layout •Localize with a single nib and multiple strings files