Skip to content
FLAVIO COPES
flaviocopes.com

SwiftUI: the Button view and updating the app state

By

Learn how to use the Button view in SwiftUI to run an action when tapped, and why you need the @State property wrapper to update your app's state.

~~~

The Button view can be used to display an interactive button element.

We can declare it in this way:

Button("Button label") {
    //this happens when it's tapped
}

Or in this way:

Button {
   //this happens when it's tapped
} label: {
   Text("Button label")
}

This second way is more common when you have something else as the label of the button, not text. For example an image.

Let’s use the first way in a SwiftUI program:

struct ContentView: View {
    var body: some View {
        Button("Test") {
            
        }
        .font(.title)
    }
}

See? There is a blue text in the app, and you can tap it. It’s interactive.

Xcode showing SwiftUI Button code and iPhone simulator displaying a blue Test button

We haven’t told it to do anything when tapped, so it does anything.

We can print something to the debugging console:

struct ContentView: View {
    var body: some View {
        Button("Test") {
            print("test")
        }
        .font(.title)
    }
}

Note that this works only when you run the app, not in the Xcode preview

Now we can add another step to our app. We’ll print a property value inside the button label:

struct ContentView: View {
    var count = 0
    
    var body: some View {
        Button("Count: \(count)") {
            
        }
        .font(.title)
    }
}

And when it’s clicked we increment the count:

struct ContentView: View {
    var count = 0
    
    var body: some View {
        Button("Count: \(count)") {
            self.count += 1
        }
        .font(.title)
    }
}

But the app will not compile, with the error

Left side of mutating operator isn't mutable: 'self' is immutable

We need to use the @State property wrapper before we declare the property:

struct ContentView: View {
    @State var count = 0
    
    var body: some View {
        Button("Count: \(count)") {
            self.count += 1
        }
        .font(.title)
    }
}

The app will now work and we can click the label to increment the count property value:

Xcode showing SwiftUI @State count code and iPhone simulator displaying Count: 6 button

Of course the counter will start from 0 the next time we run it, because we are not persisting the state in any way. We’ll get to that later.

Tagged: Swift · All topics
~~~

Related posts about swift: