components
play

Components Ari Grant Our Journey Layout of a feed story Code for - PowerPoint PPT Presentation

Components Ari Grant Our Journey Layout of a feed story Code for a feed storys header Components Building blocks Data pipeline Optimizations NEWS FEED News Feed News Feed News Feed News Feed News Feed News Feed


  1. Components Ari Grant

  2. Our Journey • Layout of a feed story • Code for a feed story’s header • Components • Building blocks • Data pipeline • Optimizations

  3. NEWS FEED

  4. News Feed

  5. News Feed

  6. News Feed

  7. News Feed

  8. News Feed

  9. News Feed

  10. News Feed

  11. News Feed

  12. News Feed

  13. News Feed

  14. News Feed

  15. News Feed A list of stories

  16. iOS’ View APIs -(CGSize)sizeThatFits:(CGSize)size Story { ... // Math } -(void)layoutSubviews Message Header { ... // Math } Main (UI) Thread Only! Profile Overlay Name Picture

  17. The Reality of a Complex UI On iOS • 60 fps is desired • 17 ms per frame • Text layout can take many ms • Use a background thread • Configuring many views is slow • Recycle views • Heterogeneous data • Don’t use “row-based” view-types • View sizing and layout can be slow • Do sizing and layout in the background • Views can only layout on the UI thread • Oh… • Recycling code is manually written • Oh….. • You have to juggle text- and UI-threads • Oh……. • Views are mutable and always changing • Oh……… • Layout code is lots of math • Oh………..

  18. Goals Move complexity to “behind the scenes” • Easy to layout and recycle views • One-way data flow when state changes • Encourage composition and enforce immutability • Make the worst errors impossible • Allow asynchronous computation invisibly

  19. BUILDING A FEED STORY

  20. Layout of a Feed Story

  21. Layout of a Feed Story Vertical Stack …

  22. Layout of a Feed Story Vertical Stack

  23. Layout of a Feed Story Vertical Text Stack

  24. Layout of a Feed Story Horizontal … Stack Vertical Text Stack

  25. Layout of a Feed Story Image Horizontal Stack Vertical Text Stack

  26. Layout of a Feed Story Image Horizontal Stack … Vertical Stack Vertical Text Stack

  27. Layout of a Feed Story Image Title Horizontal Label Stack Vertical Stack Vertical Timestamp Text Stack Label

  28. Layout of a Feed Story Image Title Horizontal Label Stack Vertical Stack Vertical Timestamp Text Stack Label Like Button Horizontal Comment Stack Button Share Button

  29. Layout of a Feed Story Image Horizontal Stack Vertical Stack Title Label Timestamp Label Vertical Text Stack Like Button Horizonal Comment Stack Button Share Button

  30. Layout of a Feed Story Image Horizontal Stack Vertical Stack Title Label Timestamp Label Vertical Text Stack Horizontal Stack Like Button Comment Button Share Button

  31. Layout of a Feed Story Horizontal Stack Image Vertical Stack Title Label Timestamp Label Vertical Stack Text Horizontal Stack Like Button Comment Button Share Button

  32. Layout of a Feed Story Vertical Stack Horizontal Stack Image Vertical Stack Title Label Timestamp Label Text Horizontal Stack Like Button Comment Button Share Button

  33. Feed Story Header Horizontal Stack <Stack direction=“horizontal” spacing=10> Image <Image contents={image} /> <Stack direction=“vertical” spacing=12> Vertical Stack <Label text={title} /> Title Label <Label text={timestamp} /> </Stack> Timestamp Label </Stack>

  34. Feed Story Header [CPStackLayoutComponent newWithStyle:{ ... Horizontal Stack } children:{ Image ... }] Vertical Stack Title Label Timestamp Label

  35. Feed Story Header [CPStackLayoutComponent newWithStyle:{ ... Horizontal Stack } children:{ children:@[ Image ? ... ... }] ] Vertical Stack Title Label children:{ Timestamp Label {[Foo new], .bar = 7}, {[Baz new]} } children:@[ [StackLayoutChild newWithComponent:[Foo new] bar:7], [StackLayoutChild newWithComponent:[Baz new]] ]

  36. Feed Story Header [CPStackLayoutComponent newWithStyle:{ ... Horizontal Stack } children:{ Image ... }] Vertical Stack Title Label Timestamp Label

  37. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ ... Vertical Stack }] Title Label Timestamp Label

  38. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ {[CPImageComponent newWithImage:image]}, Vertical Stack ... Title Label }] Timestamp Label

  39. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ {[CPImageComponent newWithImage:image]}, Vertical Stack {[CPStackLayoutComponent Title Label newWithStyle:{ ... Timestamp Label } children:{ ... }]} }]

  40. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ {[CPImageComponent newWithImage:image]}, Vertical Stack {[CPStackLayoutComponent Title Label newWithStyle:{ .direction = CPStackLayoutDirectionVertical, Timestamp Label .spacing = 12 } children:{ ... }]} }]

  41. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ {[CPImageComponent newWithImage:image]}, Vertical Stack {[CPStackLayoutComponent Title Label newWithStyle:{ .direction = CPStackLayoutDirectionVertical, Timestamp Label .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, ... }]} }]

  42. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, Horizontal Stack .spacing = 10 } Image children:{ {[CPImageComponent newWithImage:image]}, Vertical Stack {[CPStackLayoutComponent Title Label newWithStyle:{ .direction = CPStackLayoutDirectionVertical, Timestamp Label .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, {[CPLabelComponent newWithText:timestamp]} }]} }]

  43. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, .spacing = 10 } children:{ {[CPImageComponent newWithImage:image]}, {[CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionVertical, .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, {[CPLabelComponent newWithText:timestamp]} }]} }]

  44. Feed Story Header [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, .spacing = 10 } children:{ {[CPImageComponent newWithImage:image]}, {[CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionVertical, .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, {[CPLabelComponent newWithText:timestamp]} }]} }]

  45. Feed Story Header return [super newWithComponent: [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, .spacing = 10 } children:{ {[CPImageComponent newWithImage:image]}, {[CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionVertical, .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, {[CPLabelComponent newWithText:timestamp]} }]} }] ];

  46. Feed Story Header + (instancetype)newWithImage:(UIImage *)image title:(NSString *)string timestamp:(NSString *)timestamp { return [super newWithComponent: [CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionHorizontal, .spacing = 10 } children:{ {[CPImageComponent newWithImage:image]}, {[CPStackLayoutComponent newWithStyle:{ .direction = CPStackLayoutDirectionVertical, .spacing = 12 } children:{ {[CPLabelComponent newWithText:title]}, {[CPLabelComponent newWithText:timestamp]} }]} }] ]; }

  47. Feed Story Header + (instancetype)newWithImage:(UIImage *)image title:(NSString *)string timestamp:(NSString *)timestamp { CPComponent *component = storyHeader(image, title, timestamp); return [super newWithComponent:component]; } static CPComponent *storyHeader(UIImage *image, NSString *title, NSString *timestamp) { return ...; }

  48. Feed Story Header @interface StoryHeaderComponent : CPCompositeComponent + (instancetype)newWithImage:(UIImage *)image title:(NSString *)string timestamp:(NSString *)timestamp; @end @implementation StoryHeaderComponent + (instancetype)newWithImage:(UIImage *)image title:(NSString *)string timestamp:(NSString *)timestamp { CPComponent *component = storyHeader(image, title, timestamp); return [super newWithComponent:component]; } @end

  49. COMPONENTS

  50. Wrapping a View [CPComponent newWithView:{ [UIView class], { { @selector(setBackgroundColor:), [UIColor orangeColor] }, { @selector(setAlpha:), @0.5 }, } } size:{} ] [CPComponent newWithView:{ [UIImageView class], { { @selector(setImage:), [UIImage imageNamed:@“toaster.png”] }, } } size:{} ]

  51. Sizing A Component [CPComponent newWithView:{ [UIView class], { { @selector(setBackgroundColor:), [UIColor orangeColor] }, { @selector(setAlpha:), @0.5 }, } } { width, height } size:{ 100, 200 } ] { 100, Percent(50) } { .minWidth = 50, .maxWidth = 250, { Percent(100), 200 } .minHeight = 0, .maxHeight = Percent(100), { Percent(100), Percent(50) } } { Auto(), Auto() } “Autonomous” {}

Recommend


More recommend