Skip to content

SwiftUI: the Button view and updating the app 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.

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:

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.


→ Get my Swift Handbook

download all my books for free

  • javascript handbook
  • typescript handbook
  • css handbook
  • node.js handbook
  • astro handbook
  • html handbook
  • next.js pages router handbook
  • alpine.js handbook
  • htmx handbook
  • react handbook
  • sql handbook
  • git cheat sheet
  • laravel handbook
  • express handbook
  • swift handbook
  • go handbook
  • php handbook
  • python handbook
  • cli handbook
  • c handbook

subscribe to my newsletter to get them

Terms: by subscribing to the newsletter you agree the following terms and conditions and privacy policy. The aim of the newsletter is to keep you up to date about new tutorials, new book releases or courses organized by Flavio. If you wish to unsubscribe from the newsletter, you can click the unsubscribe link that's present at the bottom of each email, anytime. I will not communicate/spread/publish or otherwise give away your address. Your email address is the only personal information collected, and it's only collected for the primary purpose of keeping you informed through the newsletter. It's stored in a secure server based in the EU. You can contact Flavio by emailing flavio@flaviocopes.com. These terms and conditions are governed by the laws in force in Italy and you unconditionally submit to the jurisdiction of the courts of Italy.

Related posts about swift: