Your First iOS & SwiftUI App: Polishing the App

Mar 1 2022 · Swift 5.5, iOS 15, Xcode 13

Part 2: Swift Coding Challenges

19. Draw the Rings

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 18. Challenge: Start Over Next episode: 20. Challenge: Draw the Rings
Transcript: 19. Draw the Rings

If we compare the current look of Bullseye to Luke’s design, one big thing stands out to me: Luke’s designs has these cool rings on the background, but we of course don’t have that yet.

Let’s fix that. But first, let’s look at Luke’s design to see what we need to do exactly.

If you look at Luke’s design, you’ll see that we see five rings. They start small, at a certain color. And each ring after that gets bigger, and gets more and more transparent: from 80% opacity down to 20% opacity.

We can think of each of these rings as a simple SwiftUI circle shape, with a stroke. If we look at Figma, it seems that each circle has a 20 pixel stroke.

The first circle is about 100x100, and the next is 200x200, and so on. So we can basically make each circle a little bit bigger than the previous.

So how do can we implement this in SwiftUI? Well, we could make a view with a ZStack, and write 5 lines of code, 1 line for each circle.

But if we did it that way, we’d have a lot of repeated code. Luckily, SwiftUI provides an easier way: ForEach.

ForEach is a construct in SwiftUI that allows you to loop over a range or a collection of values, and then create a View for each of those elements.

In this case, we can use ForEach to loop over the range of 1 to 5, and then make one View for each element in that range. So Cirrcle #1, circle #2, and so on, all the way up to #5.

The advantage of using ForEach is it avoids repeating code, and make the code much more scalable. For example, if later we decide we actually want 10 rings, we just need to update one number.

Let’s see how this works.

Add to BackgroundView.swift:

struct RingsView: View {
  var body: some View {
    ZStack {
      Color("BackgroundColor").edgesIgnoringSafeArea(.all)
      Circle()
        .stroke(lineWidth: 20)
        .frame(width: 100, height: 100)
    }
  }
}

Go to BackgroundView and modify .background():

.background(
  RingsView()
)

Modify rings code as follows:

ForEach(1..<5) { ring in
  let size = CGFloat(ring * 100)
  Circle()
    .strokeBorder(lineWidth: 20)
    .frame(width: size, height: size)
}