Auto Layout Under Control @ Pragma conference 2013

3,411 views

Published on

Slides from Auto Layout Under Control @ Pragma conference 2013

Published in: Technology, Business

Auto Layout Under Control @ Pragma conference 2013

  1. 1. Auto Layout Under Control Giuseppe Arici iOS & OS X Developer
  2. 2. Speaker • Giuseppe Arici • #pragma mark § Founder, Preacher & VP ;-) • Tiltap & Superpartes § iOS & (OS X) Developer • [ lk | tt | fb ] / giuseppearici § giuseppe@pragmamark.org
  3. 3. Session 1. Auto Layout Theory 2. Interface Builder Practice 3. Coding Practice 4. Special Cases 5. Compatibility & Migration 6. Final Thoughts
  4. 4. 1/6 Auto Layout Theory
  5. 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. 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. 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
  8. 8. Definition Auto Layout is a constraint-based, descriptive layout system.
  9. 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₂
  10. 10. 1 Solution
  11. 11. Ø Solution
  12. 12. ∞ Solutions
  13. 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. 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. 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. 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. 17. Compression Resistance nameView ageView • Which of two views will shrink to fit into this space? [self.nameView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
  18. 18. Hugging nameView ageView • Which of two views will expand to fill the space? [self.nameView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
  19. 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
  20. 20. The Rendering Process 3 PHASES Constraints Layout Display
  21. 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. 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. 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
  24. 24. 2/6 Interface Builder Practice
  25. 25. Why ? • Easier to understand than Auto Layout code • Easier to implement than Auto Layout code • Easier to debug than Auto Layout code
  26. 26. Why Not ? • Xcode 4 (FOUR) Interface Builder can be a real pain in the … • Some complex views are hard to work with ! • Why Not Storyboards ?
  27. 27. Use Auto Layout
  28. 28. New Age 5
  29. 29. New Workflow Initial Layout Maintain 5 Debug & Resolve Add Constraints
  30. 30. Initial Layout Initial Layout • Add, dispose and resize views • Add constraints when you are ready • Fix position and size
  31. 31. Add Constraints • Add Constraints with Control-Drag • Add Constraints with Align and Pin Menus • Add Missing or Suggested Constraints Add Constraints
  32. 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. 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. 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. 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. 36. Wrong Intermediate States • Ambiguous Layout: Not enough information { ∞ solutions • Conflicting Constraints: Too much information { Ø solution • Misplaced Views: Mismatched position or size
  37. 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. 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. 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
  40. 40. Missing Constraints • To add missing constraints:
 Choose Issues > Add Missing Constraints
  41. 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. 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. 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. 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. 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
  46. 46. Maintain • Keep your customers happy :-) Maintain
  47. 47. 3/6 Coding Practice
  48. 48. NSLayoutConstraint 2 methods only !
  49. 49. WithItem nameView 20 ageView nameView.right = ageView.left - 20 [NSLayoutConstraint constraintWithItem:self.nameView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.ageView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-20.0];
  50. 50. WithVisualFormat nameView 20 ageView nameView.right = ageView.left - 20 NSDictionary *views = ↳ NSDictionaryOfVariableBindings(self.nameView, self.ageView); ! NSArray *constraints = [NSLayoutConstraint ↳ constraintsWithVisualFormat:@"[nameView]-20-[ageView]" options:0 metrics:nil views:views];
  51. 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. 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. 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. 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];
  55. 55. Debugging Code • In lldb shell call the method _autolayoutTrace to find issues (lldb) po [[UIWindow keyWindow] _autolayoutTrace] ! *<UIWindow:0x8d6de00> - AMBIGUOUS LAYOUT | *<UIView:0x8b24ad0> | | *<UIButton:0x8b24cb0> | | | | | *<_UILayoutGuide:0x8b27050> - AMBIGUOUS LAYOUT | | *<_UILayoutGuide:0x8b275a0> - AMBIGUOUS LAYOUT <UIButtonLabel:0x8b2c080>
  56. 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. 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 )>,
  58. 58. 4/6 Special Cases
  59. 59. Equal Spacing Views • Tip: create spacer views between the visible views ! • spacer1 | view1 | spacer2 | view2 | spacer3
  60. 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. 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. 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 !
  63. 63. 5/6 Compatibility & Migration
  64. 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. 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. 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. 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
  68. 68. 6/6 Final Thoughts
  69. 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. 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. 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. 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. 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 !
  74. 74. Thank you ! Giuseppe Arici giuseppe@pragmamark.org

×