Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Autolayout Primer

Autolayout Primer

This is a presentation I gave at an internal meeting at iCapps on 20131204.

Tom Adriaenssen

December 04, 2013
Tweet

More Decks by Tom Adriaenssen

Other Decks in Programming

Transcript

  1. I love... ‣ ... my wife ‣ ... my 4

    kids ‣ ... to code ‣ ... to play a game of squash ‣ ... good beer
  2. I open sourced... ... some code: ‣ IIViewDeckController: “An implementation

    of the sliding functionality found in the Path 2.0 or Facebook iOS apps.” ‣ IIDateExtensions ‣ IIPopoverStatusItem See: http://github.com/inferis
  3. Agenda ‣ What is Autolayout? ‣ What is a constraint?

    ‣ Autolayout in Xcode designer ‣ Autolayout in code
  4. What is Autolayout? Auto%Layout%is%a%system%that%lets%you%lay%out%your%app’s%user%interface%by% creating%a%mathematical%description%of%the%relationships%between%the% elements.%% According to the Apple

    Docs: ‣ Keywords: ‣ mathematical ‣ relationships ‣ Eh? ‣ Developer defines constraints on/between elements ‣ constraints translate into mathematical functions ‣ UIKit/Appkit tries to solve these functions
  5. What is Autolayout? ‣ Correctly using autolayout requires you to

    change thinking ‣ Autolayout works in a different way than what you were used to ‣ Don't go calculating frames anymore ‣ Define how an element should behave according to it's peers: ‣ parent ‣ siblings ‣ Don't think in absolute terms, but think in relational terms ‣ Think flexible: it's not because an element has a certain size at one point, it will have the same size at another point
  6. Constraint a%mathematical%representation%of%a%human:expressable%statement% "the left edge should be 20pt of the

    superviews left edge" view.left = (superview.left + 20) y = m * x + c (y%=%attribute1%=%view.left)% (x%=%attribute2%=%superview.left)% (m%=%multiplier%=%1)% (c%=%constant%=%20)
  7. //%firstItem.firstAttribute%{==,<=,>=}%secondItem.secondAttribute%*%multiplier%+%constant% ! @property%(readonly,%assign)%id%firstItem;% @property%(readonly)%NSLayoutAttribute%firstAttribute;% @property%(readonly)%NSLayoutRelation%relation;% @property%(readonly,%assign)%id%secondItem;% @property%(readonly)%NSLayoutAttribute%secondAttribute;% @property%(readonly)%CGFloat%multiplier;% ! @property%CGFloat%constant;

    Constraint ‣ two items with an attribute ‣ constant ‣ relation ‣ multiplier ‣ priority level //%firstItem.firstAttribute%{==,<=,>=}%secondItem.secondAttribute%*%multiplier%+%constant% ! @property%(readonly,%assign)%id%firstItem;% @property%(readonly)%NSLayoutAttribute%firstAttribute;% @property%(readonly)%NSLayoutRelation%relation;% @property%(readonly,%assign)%id%secondItem;% @property%(readonly)%NSLayoutAttribute%secondAttribute;% @property%(readonly)%CGFloat%multiplier;% ! @property%CGFloat%constant;
  8. Attribute? ‣ left ‣ right ‣ top ‣ bottom ‣

    leading ~ left or right depending on language settings ‣ trailing ~ right or left depending on language settings ‣ width ‣ height ‣ centerX ‣ centerY ‣ baseline
  9. Multiplier? ‣ Apply modifier to attribute of source item ‣

    Cannot be set using the designer ‣ Can be set in code
  10. Relation? ‣ equal ‣ less than or equal ‣ greater

    than or equal ! ‣ if you want just "less than" or "greater than", adjust the constant
  11. Priority ‣ constraints with higher priority are satisfied before constraints

    with lower priority ‣ Default = UILayoutPriorityRequired (1000) ‣ Other predefined priorities ‣ UILayoutPriorityRequired = 1000 ‣ UILayoutPriorityDefaultHigh = 750 ‣ Default content compression priority ‣ UILayoutPriorityDefaultLow = 250 ‣ Default content hugging priority ‣ UILayoutPriorityFittingSizeLevel = 50 ‣ You can use any integer value between 0-1000
  12. Pitfalls ‣ constraints are cumulative ‣ constraints do not override

    each other ‣ adding a second width constraint does not remove or override a previous one ‣ remove first one manually ‣ constraints can cross view hierarchy ‣ add constraint from view to superview of superview ‣ only if scope of view hierarchy uses autolayout! (no custom framesetting)
  13. Intrisic Content Size ‣ applicable to leaf views (views with

    no subviews) ‣ view knows what size it wants to be (eg UIButton) ‣ autolayout will size view to its intristic content size if no constraints control the width/height :%(CGSize)intrinsicContentSize; Returns%the%natural%size%for%the%receiving%view,%considering% only%properties%of%the%view%itself.% ‣ You can override this method in a subclass to change the default behavior ‣ return UIViewNoIntrinsicMetric when there's no intristic size defined for an axis
  14. Compression resistance & Content hugging ‣ Content Compression resistance? ‣

    defines how the view's frame resist compressing it's content ‣ Content hugging? ‣ defines how the view's frame should hug it's content
  15. Compression resistance & Content hugging Say you've got button like

    this: % |[%%%%%%%Click%Me%%%%%%]|% and you've pinned the edges to a larger superview with priority 500. ! Then, if hugging priority > 500 it'll look like this: % |[Click%Me]%%%%%%%%%%%%%|% If hugging priority < 500 it'll look like this: % |[%%%%%%%Click%Me%%%%%%]|% ! If the superview now shrinks and if the compression resistance priority > 500, it'll look like this % |[Click%|Me]% else if compression resistance priority < 500, it could look like this: % |[Cli..]|
  16. Autolayout in code: 3 options ‣ Write constraints manually ‣

    HEAD WILL EXPLODE ‣ Use visual format ‣ HEAD WILL EXPLODE MOAR ‣ Use UIView+AutoLayout Cocoapod ‣ Provides descriptive methods creating constraints ‣ Still verbose but quite readable ‣ Best of both worlds
  17. Autolayout in code ‣ Important note when creating constraints in

    code ‣ If you create a view manually, use: ! ! ‣ if you don’t, you’ll get a lot of constraint errors! view%=%[UIView%new];% view.translatesAutoresizingMaskIntoConstraints%=%NO;
  18. UIView+AutoLayout ‣ Available as a CocoaPod ‣ Implements a category

    on UIView. ‣ Easy creation of 1 or more NSLayoutConstraints. ‣ Some methods return 1 constraint, some an NSArray containing constraints ‣ Does not add constraints, just creates them ‣ you need to add them yourself :(void)addConstraint:(NSLayoutConstraint%*)constraint;% :(void)addConstraints:(NSArray%*)constraints;
  19. UIView+AutoLayout :%(NSLayoutConstraint%*)autoPinEdgeToSuperviewEdge:(ALEdge)edge%withInset: (CGFloat)inset;% ‣ Pins the given edge of the

    view to the same edge of the superview with an inset. ! :%(NSLayoutConstraint%*)autoPinEdgeToSuperviewEdge:(ALEdge)edge%withInset: (CGFloat)inset%relation:(NSLayoutRelation)relation;% ‣ Pins the given edge of the view to the same edge of the superview with an inset as a maximum or minimum. ! :%(NSArray%*)autoPinEdgesToSuperviewEdgesWithInsets:(UIEdgeInsets)insets;% ‣ Pins the edges of the view to the edges of its superview with the given edge insets. Pin to superview edges
  20. UIView+AutoLayout :%(NSLayoutConstraint%*)autoPinEdge:(ALEdge)edge%% %%%%%%%%%%%%%%toPositionInSuperview:(CGFloat)value;% ‣ Pins the given edge of the

    view to a fixed position (X or Y value, depending on edge) in the superview. Pin at point in superview
  21. UIView+AutoLayout :%(NSArray%*)autoCenterInSuperview;% ‣ Centers the view in its superview. !

    :%(NSLayoutConstraint%*)autoCenterInSuperviewAlongAxis:(ALAxis)axis;% ‣ Centers the view along the given axis (horizontal or vertical) within its superview. ! :%(NSLayoutConstraint%*)autoPinCenterAxis:(ALAxis)axis% %% % % % %%%toPositionInSuperview:(CGFloat)value;% ‣ Pins the given center axis of the view to a fixed position (X or Y value, depending on axis) in the superview. Centering in superview
  22. UIView+AutoLayout :%(NSLayoutConstraint%*)autoPinEdge:(ALEdge)edge%toEdge:(ALEdge)toEdge% ofView:(UIView%*)peerView;% ‣ Pins an edge of the view

    to a given edge of another view. ! :%(NSLayoutConstraint%*)autoPinEdge:(ALEdge)edge%toEdge:(ALEdge)toEdge% ofView:(UIView%*)peerView%withOffset:(CGFloat)offset;% ‣ Pins an edge of the view to a given edge of another view with an offset. ! :%(NSLayoutConstraint%*)autoPinEdge:(ALEdge)edge%toEdge:(ALEdge)toEdge% ofView:(UIView%*)peerView%withOffset:(CGFloat)offset%relation: (NSLayoutRelation)relation;% ‣ Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. Pin to other views
  23. UIView+AutoLayout :%(NSLayoutConstraint%*)autoAlignAxis:(ALAxis)axis%% %%%%%%%%%%%%%%%%%%%%%toSameAxisOfView:(UIView%*)peerView;% ‣ Aligns an axis of the view

    to the same axis of another view. ! :%(NSLayoutConstraint%*)autoAlignAxis:(ALAxis)axis%% %%%%%%%%%%%%%%%%%%%%%toSameAxisOfView:(UIView%*)peerView%% %% % % % % %%%%%%withOffset:(CGFloat)offset;% ‣ Aligns an axis of the view to the same axis of another view with an offset. Aligning views
  24. UIView+AutoLayout :%(NSArray%*)autoSetDimensionsToSize:(CGSize)size;% ‣ Sets the view to a specific size.

    ! :%(NSLayoutConstraint%*)autoSetDimension:(ALDimension)dimension%% % % % % % % % % %toSize:(CGFloat)size;% ‣ Sets the given dimension of the view to a specific size. ! :%(NSLayoutConstraint%*)autoSetDimension:(ALDimension)dimension%% %%% % % % % % % % %toSize:(CGFloat)size%% % % % % % % % %%%relation:(NSLayoutRelation)relation;% ‣ Sets the given dimension of the view to a specific size as a maximum or minimum. View dimensions
  25. UIView+AutoLayout :%(NSLayoutConstraint%*)autoMatchDimension:(ALDimension)dimension%toDimension: (ALDimension)toDimension%ofView:(UIView%*)peerView;% ‣ Matches a dimension of the view

    to a given dimension of another view. :%(NSLayoutConstraint%*)autoMatchDimension:(ALDimension)dimension%toDimension: (ALDimension)toDimension%ofView:(UIView%*)peerView%withOffset:(CGFloat)offset;% ‣ Matches a dimension of the view to a given dimension of another view with an offset. :%(NSLayoutConstraint%*)autoMatchDimension:(ALDimension)dimension%toDimension: (ALDimension)toDimension%ofView:(UIView%*)peerView%withOffset:(CGFloat)offset%relation: (NSLayoutRelation)relation;% ‣ Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. :%(NSLayoutConstraint%*)autoMatchDimension:(ALDimension)dimension%toDimension: (ALDimension)toDimension%ofView:(UIView%*)peerView%withMultiplier:(CGFloat)multiplier;% ‣ Matches a dimension of the view to a multiple of a given dimension of another view. :%(NSLayoutConstraint%*)autoMatchDimension:(ALDimension)dimension%toDimension: (ALDimension)toDimension%ofView:(UIView%*)peerView%withMultiplier:(CGFloat)multiplier% relation:(NSLayoutRelation)relation;% ‣ Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. View dimension matching
  26. UIView+AutoLayout +%(void)autoSetPriority:(UILayoutPriority)priority%% %%%%%%%%%forConstraints:(ALConstraintsBlock)block;% ‣ Sets the constraint priority to the

    given value for all constraints created using the UIView+AutoLayout category API within the given constraints block. ‣ NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added using the SDK directly within the block! ‣ Use the auto… methods of UIView+AutoLayout Priorities
  27. UIView+AutoLayout :%(void)autoRemoveConstraintsAffectingView;% ‣ Removes all explicit constraints that affect the

    view. :%(void)autoRemoveConstraintsAffectingViewAndSubviews;% ‣ Recursively removes all explicit constraints that affect the view and its subviews. Additional%methods%if%you%do%want%to%remove%the% :%(void)autoRemoveConstraintsAffectingViewIncludingImplicitConstraints: (BOOL)shouldRemoveImplicitConstraints;% ‣ Removes all constraints that affect the view, optionally including implicit constraints. : (void)autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstra ints:(BOOL)shouldRemoveImplicitConstraints;% ‣ Recursively removes all constraints from the view and its subviews, optionally including implicit constraints. Removal of constraints
  28. UIView+AutoLayout Removal of constraints ‣ A little bit of a

    warning when removing constraints: ‣ The constraint solving engine is not optimised for the removal of constraints ‣ Removing a lot of constraints can have serious impact on performance ‣ Use with care and in small quantities ‣ You can change the priority of a constraint to “disable” it (but you have to remember the original value to reenable it)
  29. UIView+AutoLayout ‣ category on NSArray doing the same for groups

    of views ‣ category on NSLayoutConstraint to remove a constraint from the view it's attached to Other stuff
  30. Protips ‣ Where to add which constraints? ‣ When constraints

    only apply to 1 view (eg setting dimensions) ‣ create on view ‣ add to view ‣ When constraints apply to more than 1 view eg pin one view to another ‣ create on target view ‣ add to common superview of both views (usually the same)
  31. Protips ‣ Check for autotranslated autoresizing constraints ‣ don’t forget

    translatesAutoresizingMaskIntoConstraints ‣ Display the view hierarchy from the root to find where things go wrong ‣ errors don’t provide any context ! ‣ look for address of view giving errors, and then you’ll get an idea of what context the error is happing in po%[[[[UIApplication%sharedApplication]%windows]% objectAtIndex:0]%recursiveDescription]
  32. Protips ‣ Don’t assume a view has a fixed size

    ‣ (unless you give it a size constraint) ‣ initWithFrame: not really useful anymore ‣ Don’t use frame/bounds calculations in constraints ‣ exception: in layoutSubViews ‣ Try to minimalise the number of constraints ‣ solving takes time ‣ more constraints, more complex
  33. Protips ‣ animating constraints ‣ set constraints outside animation block

    ‣ call layoutIfNeeded in animation ‣ Make sure you do this on the correct “top level view” otherwise nothing will animate! self.offsetConstraint.constant%=%[self%calculateOffset];% [UIView%animationWithDuration:0.3%animations:^{% % [self.view%layoutIfNeeded];% }];
  34. Protips ‣ when changing content: ‣ don’t forget to update

    constraints ‣ call setNeedsUpdateConstraints ‣ let the system decide when to update ‣ or updateConstraintsIfNeeded ‣ immediate action ‣ only needed when your constraint change might affect other constraints ‣ don’t forget to relayout your views ‣ call setNeedsLayout ‣ or layoutIfNeeded
  35. Useful References ‣ Apple’s autolayout documentation: ‣ reference: https://developer.apple.com/library/ios/ documentation/userexperience/conceptual/

    AutolayoutPG/Introduction/Introduction.html ‣ Martin Pilkington’s iOSDevUK2013 slides on autolayout solving ‣ http://www.iosdevuk.com/storage/talks2013/ MartinPilkington.pdf ‣ UIView+AutoLayout ‣ https://github.com/smileyborg/UIView-AutoLayout