Auto Layout Under Control @ Pragma conference 2013

Post on 09-May-2015

2.461 views 0 download

description

Slides from Auto Layout Under Control @ Pragma conference 2013

Transcript of Auto Layout Under Control @ Pragma conference 2013

Giuseppe AriciiOS & OS X Developer

Auto Layout Under Control

Speaker•Giuseppe Arici

• #pragma mark § Founder, Preacher & VP ;-)

•Tiltap & Superpartes § iOS & (OS X) Developer

• [ lk | tt | fb ] / giuseppearici § giuseppe@pragmamark.org

Session1. Auto Layout Theory

2. Interface Builder Practice

3. Coding Practice

4. Special Cases

5. Compatibility & Migration

6. Final Thoughts

1/6 Auto Layout Theory

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

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

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

Definition

Auto Layout is aconstraint-based,

descriptive layout system.

Mathematical Background•System of Linear Equations: Linear Algebra

•System of Linear Equations: Cartesian Plane

a₁₁x + a₁₂y = b₁a₂₁x + a₂₂y = b₂{

{y = m₁x + c₁y = m₂x + c₂

1 Solution

Ø Solution

Solutions∞

Constraint Basics

• 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: =, <=, >=

y ☺ mx + c

Constraint Basics

•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)

view.leading >= (superview.leading + 20)

Constraint Priority

•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

nameView ageView

@750 @250

•How large is intrinsically the content of a leaf-level view, such a button, a label, an imageView, … ?

Intrinsic Content Size

- (CGSize)intrinsicContentSize { NSDictionary *attributes = @{ NSFontAttributeName : [UIFont systemFontOfSize:17.0f], }; return [self.text sizeWithAttributes:attributes]; }

Follow us @pragmamarkorg

Compression Resistance

•Which of two views will shrink to fit into this space?

nameView ageView

[self.nameView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];

Hugging

•Which of two views will expand to fill the space?

nameView ageView

[self.nameView setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];

• Install constraints on views

•Convert constraints into inequalities

•Solve system of inequalities all at once

•Update views frames

•Display layers on screen

How Auto Layout Works

{ y = m₁x + c₁y = m₂x + c₂

The Rendering Process

Constraints Layout Display

3 PHASES

Constraints Phase•From subview to superview

•Trigger via setNeedsUpdateConstraints

•Add custom view constraints via updateConstraints

•Prepares each view with the values it needs to set frames

main view

subview

superview

container view

label view

Layout Phase•From superview to subview

•Can be triggered via setNeedsLayout

•Force instant-refresh via layoutIfNeeded

•Applies the frames from the previous step to each view

main view

subview

superview

container view

label view

Display Phase•From superview to subview

•Can be triggered via setNeedsDisplay

•Same as Springs & Struts

•drawRect: lives here

main view

subview

superview

container view

label view

2/6 Interface Builder Practice

Why ?•Easier to understand than Auto Layout code

•Easier to implement than Auto Layout code

•Easier to debug than Auto Layout code

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 ?

Use Auto Layout

New Age

5

Maintain

Debug & Resolve

Add Constraints

New WorkflowInitial Layout

5

Initial Layout

•Add, dispose and resize views

•Add constraints when you are ready

•Fix position and size

Initial Layout

Add Constraints

•Add Constraints with Control-Drag

•Add Constraints with Align and Pin Menus

•Add Missing or Suggested Constraints Add Constraints

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

Align and Pin Menus

•Align: create alignment constraints:• Edges, Center and Baseline

•Pin: create spacing constraints:• Width, Height and Distance from another view

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

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

Wrong Intermediate States

•Ambiguous Layout: Not enough information { ∞ solutions

•Conflicting Constraints: Too much information { Ø solution

•Misplaced Views: Mismatched position or size

Debug & Resolve

•See Xcode Issues Navigator

•Get detailed help using the outline view

•Follow canvas decorations

•Fix constraint via resolving menu

Debug & Resolve

Identifying Issues

!In the Issues

Navigator

!In the Interface Builder

outline view

On the canvasMisplaced or ambiguous

constraints are shown in orange, conflicting constraints are red

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

Missing Constraints

•To add missing constraints:Choose Issues > Add Missing Constraints

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 !

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 !

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

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

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

Maintain

•Keep your customers happy :-)

Maintain

3/6 Coding Practice

NSLayoutConstraint

2 methods only !

[NSLayoutConstraint constraintWithItem:self.nameView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.ageView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-20.0];

WithItem

nameView ageView20

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];

WithVisualFormat

nameView ageView20

nameView.right = ageView.left - 20

Visual Format Language

•VFL aka ASCII Art ;-)

•Orientation: V or H

•Superview: | |

•Relation: >=, <=, ==

•Priority:•[view(<=width@contentHugging)] •[view(>=width@contentCompressionResistance)]

@"H:|[nameView]-20-[ageView]|"

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)]-|

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:

nameView

3 * H

H

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];

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> | | | <UIButtonLabel:0x8b2c080> | | *<_UILayoutGuide:0x8b27050> - AMBIGUOUS LAYOUT | | *<_UILayoutGuide:0x8b275a0> - AMBIGUOUS LAYOUT

• In lldb shell change the color of a view to find it by memory

Debugging Code

(lldb) expr ((UIView *)0x8b24cb0).backgroundColor = [UIColor redColor] (id) $1 = 0x08c1f190

Debugging Code• In lldb shell log constraints with methods:

• constraints

• constraintsAffectingLayoutForAxis: in iOS | constraintsAffectingLayoutForOrientation: in OS X

(lldb) po [[self button1] constraints]

<__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] (Names: '|':UIView:0x8c2b1c0 )>,

<NSLayoutConstraint:0x8c28480 H:[UIButton:0x8c28df0(80)]>

)

Log uses VFL !

4/6 Special Cases

Equal Spacing Views

•Tip: create spacer views between the visible views !

• spacer1 | view1 | spacer2 | view2 | spacer3

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

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

[containerView layoutSubtreeIfNeeded]; [UIView animateWithDuration:1.0 animations:^{ self.nameViewWidthConstraint.constant = finalConstant; [containerView layoutSubtreeIfNeeded]; }];

Animations

•make constraint changes

•don’t animate the frame

• call layoutSubtreeIfNeeded

•change only the constant !

y ☺ multiplier * x + constant

5/6 Compatibility & Migration

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

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);

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

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

6/6 Final Thoughts

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

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

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

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

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 !

Thank you !

Giuseppe Aricigiuseppe@pragmamark.org