SwiftUI State Tutorial

State is a value, or a set of values, that can change and that affects a view’s behavior, content, or layout. In this tutorial a toggle is created which will determine if a user is logged in or not. . SwiftUI requires Xcode 11 and MacOS Catalina, for which the Betas can be downloaded at the Apple developer portal.

Open Xcode and either click Create a new Xcode project in Xcode’s startup window, or choose File > New > Project. In the template selector, select iOS as the platform, select the Single View App template, and then click Next. Enter SwiftUIStateTutorial as the Product Name, select the Use SwiftUI checkbox, and click Next. Choose a location to save the project on your Mac.

In the canvas, click Resume to display the preview. If the canvas isn’t visible, select Editor > Editor and Canvas to show it.

All views in SwiftUI are structs. By default, all structs are immutable, which means properties cannot be changed. In the Project navigator, click to select ContentView.swift. Change the code inside the ContentView struct to

struct ContentView : View {
    var userIsLoggedIn = false
    
    var body: some View {
        VStack {
            userIsLoggedIn = true
            Text("Hello World!")
        }
    }
}

This code returns the error message: “Cannot use mutating member on immutable value: 'self' is immutable”

SwiftUI's solution for this is the use of property wrappers, a Swift feature introduced in Swift 5.1. When using property wrappers the property will be placed out of the struct and stored somewhere else.

When using the @State keyword when declaring a property, SwiftUI monitors the value. When the state value changed, the View will reload. To keep the value of the property in sync with the current value used inside the View, a "binding" must be created. This is a two-way process:

  1. When the property value changes, the state in the views need to be changed.

  2. When the state changes inside the view the property needs to be updated.

You can get a binding from a state by using the `$` prefix operator. change the ContentView struct to

struct ContentView : View {
    @State var userIsLoggedIn = false
    
    var body: some View {
        VStack {
            Toggle(isOn: $userIsLoggedIn) {
                Text("Log in")
            }.padding()
        
            if (userIsLoggedIn) {
                Text("user is logged in")
            } else {
                Text("user is logged out")
            }
        }
    }
}

Enter Live mode in the preview. When changing the state of the toggle the Text view will update.

The source code of the SwiftUStateITutorial can be downloaded at the ioscreator repository on Github.