Make a Count Up Timer using Swift and SwiftUI

07 May 2020

#swiftui #swift

In this post, we are going to make a count up timer using Swift and SwiftUI. This will walk you through step by step from making a new app to running the finished timer.

The finished project can be cloned from GitLab here.

Step 1: Launch a new project

Launch a new project in Xcode. The template needs to be a Single View App. The language needs to be set to Swift and the User Interface needs to be set to SwiftUI. You can set the Product Nameto be whatever you’d like. I’m calling mine Count Up Timer.

Image of new project

Step 2: Add variables

Let’s add variables to hold the hours, minutes, and seconds that are needed to be displayed on the screen.

In ContentView.swift, add lines 6 through 8 in the gist below.

These three variables, hours, minutes, and seconds are declared with the @State property wrapper so that the text updates when the value updates. You can read more about the @State property wrapper here on Apple’s website.

Step 3: “Design” the UI

Now, let’s actually design the UI. It’s going to have the timer in the middle, then buttons to start/pause the timer and to reset the timer back to 0.

The first thing we need to do is add a VStack in the body. To do this, you can right click on the Text("Hello, World!") and choose Embed in VStack. Your code should now look like the gist below.

Show the timer values

Then, we need to put the variabled in. We are going to change the Hello, World! to \(hours):\(minutes):\(seconds). If you open the Canvas and resume it, then you should see 0:0:0 in the device.

You might be asking why use \() around the variable name. The slash and parenthesis are needed to tell the compiler that there is code inside the parenthesis. Therefore, the program will display the contents of the variable and not the variables name.

Add Buttons

Now, let’s add the buttons and make them do something!

First, we are going to add a new state variable that signifies if the timer has started or been paused. Right after the declaration of seconds, add @State var timerIsPaused: Bool = true.

Then, after Text() we need to add an if statement that is going to show a view when the timer is paused and when it’s going. The gist below shows what the view should look like with that if statement.

Now, we are going to change Text to Buttons and use SF Symbol for Start, Pause, and Reset.

If timerIsPaused is true, then we want to show a play icon for start and a backward icon for reset. To do this, we need to use the Image(systemName: String) as the Button labels. These two buttons also need to be in a HStack to be next to each other. Now, if timerIsPaused is false, we need to show a pause icon to stop the timer. The gist below shows the buttons in the if statement.

That’s what it took to “design” this app in SwiftUI. Next, we are going to make the parts functional.

Step 4: Start the timer

It’s time to actually get the timer going. We are going to use the Timer that’s buit into Swift. We will need to make a repeating timer that adds one second every second.

Let’s add a variable for the state first, so after timerIsPaused, add @State var timer: Timer? = nil. This declares a variable to store the timer in, but doesn’t actually store a Timer to the variable, yet, since we will call a new Timer when the timer starts.

Next we need to write a function that starts the timer and changed timerIsPaused to false. The function is going to be called startTimer(). In the function, add the line timerIsPaused = false. After that, a timer needs to be added, so the gist below shows that.

Now, I’m going to explain what’s going on in lines 3 thourgh 5.

1. Make a new timer

This is where a new timer is actually made. I’m using a scheduled Timer so that every second something can be triggered.

  • withTimeInterval is used to specify how often, in seconds, each action inside the closure is executed. I have it set to 1, so that seconds is incremented each second.
  • repeats needs to be set to true so that the code in the closure is ran every 1 second. If it is set to false, then the operations in the closure is only ran one time.

2. Check time to add

This is all the code to check when to increment seconds, minutes, and hours.

I chose to use the closure method of starting a new timer so that I didn’t have to wrap the function in an objective-c caller.

Once the function is written, make sure to call it in the button. Here is what the Start button code should now look like.

Step 5: Stop the timer

It’s time for another function to actually stop the timer. The function is going to be called stopTimer(). In this timer, we need to set timerIsPaused to false and kill the timer that is currently running. To kill the timer, we call the invalidate() function on the timer, which will not allow the timer to fire again. Here is what the function looks like.

Now, make sure to call the function when the Stop button is pressed.

Here is what ContentView.swift should look like at this point.

Step 6: Reset the clock

This is the easiest function. It’s going to set hours, minutes, and seconds back to 0.

Now, call it when the reset button is pressed using self.restartTimer().

✅ The count up timer is done!

Now the count up timer is done. You should be able to run the app, start the timer, stop the timer, and reset it.


The completed project can be cloned from GitLab.