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

Swift India Conf 2019: Drawing Graphs with SwiftUI

Swift India Conf 2019: Drawing Graphs with SwiftUI

Speaker: Matthew Delves, iOS Engineer, Delightful Apps

Twitter: https://twitter.com/mattdelves/

Bio: Matt is an iOS and macOS developer who works on his own products as well as does freelance work with other companies. He is unashamedly an advocate for Storyboards and Segues. Matt is frequently caught traveling the world, enjoys cycling and is always looking for challenging climbs to ride his bike up.

Abstract: SwiftUI is the new declarative UI framework from Apple. In this talk, we'll explore how to apply this new UI to drawing graphs that are usable across both iOS and macOS by leveraging the expressiveness of SwiftUI


Swift India

July 28, 2019


  1. Drawing Graphs An adventure story about SwiftUI

  2. Hi, I'm Matt @mattdelves

  3. A word of caution All that's mentioned here is true

    as of Beta 4 This may all change at sometime soon
  4. Declarative and Imperative

  5. Declarative UI "you load your handlers and their conditions into

    the system before starting and the system runs itself to completion, calling your handlers if their conditions are met at any point" -- cocoawithlove
  6. Imperative UI "you run the system to the next lifecycle

    checkpoint and then you read state of the system, looking for specific conditions, running your code if one of those conditions are discovered" -- cocoawithlove
  7. SwiftUI The Hero

  8. The Friends • View • Shape • ScrollView • GeometryReader

  9. View struct AwesomeView: View { var body: some View {

    Text("Everything is awesome") .font(.largeTitle) } }
  10. Shape struct AwesomeShape: Shape { func path(in rect: CGRect) ->

    Path { ... } }
  11. ScrollView ScrollView(.vertical, showsIndicators: true) { ... } ScrollView(.horizontal, showsIndicators: false)

    { ... }
  12. GeometryReader GeometryReader { geometry in Text("Awesome width") .frame(width: geometry.size.width) }

  13. A hero needs her friends

  14. The body of the graph public struct LineGraph: Shape {

    public func path(in rect: CGRect) -> Path { var path = Path() let startPoint = CGPoint(x: 0, y: rect.height) let endPoint = CGPoint(x: rect.width, y: rect.height) let points = displayPoints(from: graph, in: rect) path.move(to: startPoint) path.addLines(points) path.addLine(to: endPoint) path.addLine(to: startPoint) return path } }
  15. The axis public func path(in rect: CGRect) -> Path {

    switch axis { case .x: return horizontalPath(in: rect) case .y: return verticalPath(in: rect) } }
  16. The labels public var body: some View { switch axis

    { case .x: return AnyView(xAxisLabels) case .y: return AnyView(yAxisLabels) } }
  17. The whole thing VStack(alignment: .leading, spacing: 16) { Text(graph.title) .font(.headline)

    HStack(alignment: .top, spacing: .zero) { yAxis xAxisAndGraph Spacer() .frame(width: 10) } }
  18. Scrolling ScrollView(.horizontal) { VStack(spacing: CGFloat.zero) { GraphShape(graph: self.graph) .fill(Color.blue) .frame(height:

    CGFloat(geometry.size.height - 25.0)) GraphXAxis(graph: self.graph) } .frame(width: configuration.graphWidth) }
  19. Scaling let zoomGesture = MagnificationGesture() .updating($isScaling) { currentState, gestureState, transaction

    in self.graph.scale = max(1.0, currentState) } return Graph() .gesture(zoomGesture)
  20. Modifying Content extension Graph { public func fill(_ color: Color)

    -> Graph { graph.graphColor = color return self } } GraphView() .fill(.pink)
  21. View modifiers struct PinkGraph: ViewModifier { func body(content: Content) ->

    some View { content .fill(.pink) } } GraphView() .modifier(PinkGraph())
  22. Challenges faced

  23. General advice

  24. Thanks Please keep in touch @mattdelves on the internet Am

    available for contract / freelance work