100 Days of SwiftUI Day 16

100 Days of SwiftUI – Day 16 – First Project

We’ve arrived at day 16 of the 100 Days of SwiftUI! Yesterday, we reflected on the first 2 weeks with a consolidation day. Today, we start laying the foundations for the very first real project we’ll be working on using SwiftUI. The app we’ll be making is called WeSplit. It allows users to calculate how to split the bill, taking into account a possible tip and the amount of persons. Let’s dive in!

Using forms in SwiftUI

Up until now, we’ve worked using Swift Playgrounds. Today, that changes as we start a real Xcode project. The first thing we’re working with is the ContentView, which is where we’ll do all the programming for this project.

We start with an introduction to forms. A form is used to get input from the end user and is very commonly used. An important thing to note is that a form can contain a maximum of 10 views.

Just a reminder: a view is some form of content that is displayed on the screen of the end user of the app.

struct ContentView: View {
    var body: some View {
        Form {
            Text("Hello, world!")
                .padding()
        }
    }
}

Using the navigation bar

To make sure our content does not overlap any of iOS’ system user interface, like the clock or battery for example, SwiftUI features a navigation bar. This ensures that all the content on the display will remain within what is known as the safe area.

struct ContentView: View {
    var body: some View {
        NavigationView {
            Form {
                Text("Hello, world!")
                    .padding()
            }
        }
    }
}

Modifying program state

A state is referred to as a collection of all the actively tracked data on the screen. If you were playing a game, this could be your health, amount of lives, score, etc.

struct ContentView: View {
    @State private var buttonCount = 0
    var body: some View {
        NavigationView {
            Form {
                Text("Hello, world!")
                    .padding()
                Button("This button has been pressed \(buttonCount) times") {
                    self.buttonCount += 1
                }
            }
        }
    }
}

Before we move on to the next subject, here’s an helpful tip from Paul about states:

There are several ways of storing program state in SwiftUI, and you’ll learn all of them. @State is specifically designed for simple properties that are stored in one view. As a result, Apple recommends we add private access control to those properties, like this: @State private var tapCount = 0.

Paul Hudson (@twostraws)

Binding state to user interface controls

Using a button like in the example above can be done by using a state. However, what if we’d like to get some input from a user in the form of a textfield? This would entail that Swift needs to both save what is on the screen to a variable and show it on the screen, instead of doing only the latter. This is called two-way binding: we bind the text field so that it shows the value of our property, but we also bind it so that any changes to the text field also update the property.

struct ContentView: View {
    @State private var buttonCount = 0
    @State private var name = ""
    var body: some View {
        NavigationView {
            Form {
                Text("Hello, world!")
                    .padding()
                Button("This button has been pressed \(buttonCount) times") {
                    self.buttonCount += 1
                }
                TextField("Please enter your username: ", text: $name)
                    .padding()
                Text("Your username is \(name)")
                    .padding()
            }
        }
    }
}
Xcode simulator demo for user input in SwiftUI

Creating views in a loop using ForEach

SwiftUI features a ForEach view which is used to run a closure for every item it loops over and returns a view for that item. A ForEach is also not limited to the 10 views limit like forms.

struct ContentView: View {
    @State private var buttonCount = 0
    @State private var name = ""
    var body: some View {
        NavigationView {
            Form {
                Text("Hello, world!")
                    .padding()
                Button("This button has been pressed \(buttonCount) times") {
                    self.buttonCount += 1
                }
                TextField("Please enter your username: ", text: $name)
                    .padding()
                Text("Your username is \(name)")
                    .padding()
                ForEach(0..<5) { Text("This is row number \($0+1).") }
            }
        }
    }
}
Demo of using a ForEach view loop in SwiftUI

And that was it for day 16! It was very fun to see our code come to live in the simulator and I look forward to working on the first project. As always, I hope you enjoyed the read. Onwards we go!

Darryl

Hi! My name is Darryl and this is my personal blog where I write about my journey as I learn programming! You'll also find articles about other things that interest me including games, tech and anime.

Post navigation

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

100 Days of SwiftUI – Day 59

100 Days of SwiftUI – Day 38

100 Days of SwiftUI – Day 77

100 Days of SwiftUI – Day 33