Building a Graph With SwiftUI. Learn the basics of graphs | by M Salman A | Aug, 2022

Learn the basics of graphs

0*S7kNaSsDi OwqtO4
Photo by Алекс Арцибашев on Unsplash
  • Basic knowledge of Swift (understand how to code in swift)
  • Basic knowledge of SwiftUI (understand the basic components in SwiftUI and how to use them)
  • The will to learn!

Have you ever opened a website and come across a graph visualization such as this one?

1*2fIt9Gr9P9TPpqOTn Z4nQ
A network graph visualizing similar papers

This is called a Network Graph, and is commonly used to model relationships between many items. Some applications of such a graph are to visualize friends in a social network, interconnecting cities, or even the typical food chain you find in any Biology textbook. A Network Graph consists of two components, the vertex (or vertices) and the edges. A vertex represents the items that are visualized in the graph, and the edges show the relationships between similar items.

But have you ever wondered how such graphs are made? How do you lay out each items in the graph? I won’t go into too much detail about graph theory and whether you need one in your app, but what I will show you in this article is the technical details behind showing such a visualization for your SwiftUI app.

Before we get to deep on how to build complex graph visualizations with many vertices and edges, let’s first start with a basic graph. This simple graph has two vertices and one edge. It will look something like this:

No, it’s not Baymax. It’s a graph with two vertices and one edge.

First, we start with our background. Setup a SwiftUI project in Xcode (if you don’t know how to, check out tutorials from YouTube such as this one). You should start with an empty ContainerView.

To give the background for our graph, start by creating a ZStack with a Rectangle as the first item. For the ZStack, we will give it the topLeading alignment for our coordinate system (I will explain this in a bit) and for the rectangle, just give it a fill with the color you desire for the background of your graph. I chose white.

Code snippet for our graph’s background.

Our graph works by plotting each vertex into a two-dimensional coordinate system in the ZStack. Because we gave it the topLeading alignment, the coordinate (0, 0) will start at the top left of the device screen.

Each pixel on your device screen represents a point in the coordinate system, where adding a value to the x coordinate moves our point to the right, and adding a value to the y coordinate moves our point down.

The coordinate system for our graph.

Now that we have our coordinate system, we can start by placing a vertex in the graph by using the Circle shape in SwiftUI (in reality, any shape would work but most graphs use a circle to represent a vertex).

We will modify two properties in our circle, the frame (how tall and wide our circle is) and the offset. The x and y values in the offset property of our circle dictates where the circle is placed within our graph’s coordinate system.

For example, if you input 50 for the x and y value, our circle should show up somewhere near the top left edge of our device’s screen. You can experiment with different x and y values, but you should remember that the greater the x, the more further right our circle will show up, and the greater the y, the further down our circle will be placed.

Code snippet to draw our lonely, lonely vertex.

Now you should be able to see your vertex in the preview, however, you can see it’s a bit lonely on its own. So, let’s give it a friend somewhere else within the coordinate system of our graph. For this friend, I will color her red by giving the red value to the circle’s fill property.

Code snippet for our little vertex friend. :]

Your screen should look something like this now:

Two dots. Looks like your phone has eyes now.

If it doesn’t yet, don’t worry, stay calm and review the code that you have written with the snippets above.

Now, we will make these two vertices look like they are connected to each other by drawing a line between them. First, we will create a new Swift file and name it EdgeShape.swift. In this file, we will add a new shape component to SwiftUI by creating a new Struct and making it conform to the Shape protocol and call it EdgeShape.

This struct will have two properties, start (the starting coordinate of the edge) and end (the ending coordinate of the edge). These will be of type CGPoint.

To conform to the Shape protocol, this struct must have one method, which is path(in rect:). This method defines how to draw this shape in the UI. In this method’s implementation, we will do four things:

  • Create a path object
  • Move our path to the starting coordinate by using the path.move(to:) method
  • Add a line from the starting coordinate by using the path.addLine(to:) method
  • Return our path inside the method

The code for our EdgeShape should look something like this:

Code snippet for our Edge shape.

Now we can go back to our ContentView.swift file and add the EdgeShape component inbetween our two Circle components in the ZStack to draw an Edge. First, give a start and end value to the EdgeShape constructor by creating two CGPoint objects.

For the start CGPoint, give its start x and y the same values as our black vertex’s coordinate. Then for the end CGPoint, give its start x and y the same values as our red vertex’s coordinate.

Notice how the line has still not been drawn yet even though we already used our EdgeShape component. That’s because we have only drawn a path, but we haven’t given it any color or thickness. To do so, give our EdgeShape a stroke, with optional color.

Code snippet for our first edge.

Yay! You have successfully connected your two vertices with an edge. However, you may notice that your edge seems to be out of place even though you placed your start and end coordinates correctly.

1*YpA2az bPecFlCSIc4sSzg
A stubborn edge not being in the correct place.

No worries, this behavior is totally expected, because the vertex is aligned by its top left corner to the coordinate we gave it, not the center. We will fix this, along with refactoring our code for our vertex view.

First, create a new Swift file named VertexView.swift. Import SwiftUI in the file, then create a new struct that extends View named VertexView with a body attribute of type some View.

This struct will have three other attributes, radius of type Double, color of type Color, and the coordinate of type CGPoint.

  • In the body property, we will define a Circle as we have done previously for our vertices then add a color property from our color attribute.
  • Then, give the circle its frame attribute with the width and height being the radius multiplied by 2, and an offset attribute with the x and y attributes of the respective coordinate.
  • However, we will now subtract the x and y values with the circle’s radius, to offset the circle according to its center.

Your code should look something like this:

Code snippet for our vertex view.

Now, go back to the ContentView.swift file, then replace each one of our Circle components with our newly built VertexView. Make sure to give the same CGPoint x and y values to each of the first VertexView to the start of our EdgeShape, and the second VertexView to the end of our EdgeShape.

The code should look something like this:

Final code snippet of our ContentView

Now, our UI should look something like this:

1*oJsQ4ADbfILfVxMJ8 gNqQ
The start of a graph

Next, you can experiment with the graph by adding as many vertices and edges as you’d like! Once you have done so, you can try the challenge of automatically showing the vertices and edges of the graph from an array of CGPoint objects! (hint: use an array of CGPoints with the ForEach component in SwiftUI).

If you got stuck at any point during the tutorial, here’s the full source code of the project.

Also, if you’d like, it would be really nice if you could check out this project I made using to build a Force-Directed Graph in SwiftUI from the Graph basics we have learned!

News Credit

%d bloggers like this: