Creating a Simple SwiftUI App

SwiftUI is Apple’s new framework for building user interfaces in Swift. Let’s introduce SwiftUI by creating a simple app. The app displays the number of times you tap a button. I couldn’t think of a simper app idea.

I’m going to focus on making an iOS app in the article, but you can also make a Mac version of this app. Create a macOS App project instead of an iOS project.

Apple added SwiftUI support in Xcode 11 so you must be running Xcode 11 or higher to use SwiftUI.

Create the Project

Create a single-view iOS app project. Choose SwiftUI from the User Interface menu. Deselect all the checkboxes.

When you create the project, the project navigator should look similar to the following screenshot:

ProjectNavigatorSwiftUIProjectStart

The file you’re going to edit in this article is ContentView.swift. This file contains the main view for the app’s user interface. You will be adding controls to the content view.

The Content View

Open the ContentView.swift file. You’ll see the following struct for the content view:

struct ContentView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

The body property contains the main view. In the code Apple supplies, the view consists of a label (the Text struct is a label) with the text Hello, World!. If you build and run the project, you will see the label.

Previews and the Canvas

If you look at the end of the ContentView.swift file, you’ll see the following struct:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

That struct is for displaying a preview of the view in Xcode’s canvas. The canvas is next to the Swift file in Xcode so you can view your source code and the canvas side by side..

I’m not going to use previews and the canvas in this article. I find the canvas gets in the way, is flaky, and doesn’t help much. But the canvas is there for you if you want it. You can toggle the canvas on and off using a button on the right side of the jump bar.

ToggleCanvas

The button is at the top left in the screenshot.

Change the Label

Let’s start by changing the label’s text to Taps:. Change the code for body to the following:

var body: some View {
    Text("Taps: ")
}

Build and run the project, and you should see the label’s text is Taps:.

You can modify how the text in the label looks using functions and properties of the Text struct. Start with a period. The following code displays the label in bold text:

var body: some View {
    Text("Taps: ")
        .bold()
}

The following code changes the font to the system title font:

var body: some View {
    Text("Taps: ")
        .font(.title)
}

Add a Variable to Store the Tap Count

To display the number of times someone taps the button, you need a variable to store the number of taps. Add the following code before the body variable:

@State var taps = 0

You must use the @State property wrapper so you can change the value of taps when someone taps the button. If you omit the @State part, you will get a compiler error saying that you’re trying to change an immutable value.

Now modify the label so it also shows the number of taps.

Text("Taps: \(taps)")

Build and run the project. The label will show zero taps.

Place the Label in a Stack

The next logical step is to add a button. But you can’t just add the button after the label.

var body: some View {
    Text("Taps: ")
        .font(.title)
    // This won't compile.
    Button("Tap Me") {

    }
}

The compiler will complain about that code. You have to place the label and button inside a stack. Start by placing the label inside a stack.

VStack {
    Text("Taps: \(taps)")
        .font(.title)
}

I placed the label in a vertical stack. When you add the button, it will appear below the label. Build and run the project. There aren’t any visible changes, but you’re ready to add the button now.

Add the Button

Let’s add the button to the stack in the content view.

VStack {
    Text("Taps: \(taps)")
        .font(.title)
    Button("Tap Me") {
        self.taps += 1
    }
}

The button’s title, Tap Me, is in parentheses. A closure for the button’s action (what happens when someone taps the button) follows. For this app you increment the taps variable. If you have more complicated behavior, write a function and call that function from the closure.

Build and run the project. The number of taps increases each time you tap the button.

Add Space Between the Label and Button

The app works, but there’s not much space between the label and button. Use the padding function to add some padding between the label and button.

VStack {
    Text("Taps: \(taps)")
        .font(.title)
        .padding()
    Button("Tap Me") {
        self.taps += 1
    }
}

If you supply no arguments, the padding function adds a small amount of space. To add more space, you can supply the edge to apply the padding and the amount. The following line of code provides 100 points of padding at the bottom:

.padding(.bottom, 100)

When you build and run the project, you should see better spacing between the label and button.

Challenge

Add a Reset button that sets the taps variable back to zero. Don’t forget to add padding between the two buttons. I have the project on GitHub if you get stuck.