100 Days of SwiftUI

Day 16

2026-05-04

Today we’re starting to work with SwiftUI. The preceding days were for getting some background in the Swift language itself, but for the rest of the course we will be making several apps.

This is pretty exciting!

WeSplit: Introduction

This project is a check-sharing app that calculates how to split a check based on the number of people and how much tip you want to leave.

Understanding the basic structure of a SwiftUI app

Of course I spent time changing colors. I haven’t figured out how to change the XCode navigation panel background though (it may not be possible)

Creating a form

  • Form is a dedicated View type
  • Section groups related things on the screen

Adding a navigation bar

  • iOS automatically provides a “safe zone” for the content of the app
  • this can be overridden (we can put anything anywhere on the screen)
  • navigation bar works as a way to keep the contents from scrolling behind the clock/dynamic island, etc
  • the organization of the NavigationStack to Form seems weird to me. You put the modifier on the Form not on the stack. I tried to make a second Form in the stack and give it a NavTitle but it didn’t work. When I commented out the first .navigationTitle the second one took its place.
He addresses the possibility of multiple NavTitles by mentioning Apple’s own Settings app
NavigationStack {
  Form { <form contents> }.navigationTitle("title")
}

Modifying program state

  • views are a function of their state — that everything the user can see is just the visible representation of the structs and properties in our code
  • @State makes a “property wrapper” so your struct ContentView: View can have updatable properties
  • @State is specifically designed for simple properties that are stored in one view
  • keeping structs small is good for performance
  • let’s play with buttons!
  • interesting that Button makes a clickable object, but does not make a button shape

Binding state to user interface controls

  • given the example of a TextField — in order for Swift to both read from and write to a state variable (two-way binding), the parameter in the UI call needs a $ in front of it
  • if you’re only reading the value you don’t need the $ marker
  TextField("Enter your name", text: $name)
  Text("Hello, \(name)!")

Creating views in a loop

  • ForEach can loop over arrays and ranges, creating as many views as needed
  • For example, a Picker with a list of names to choose from
  • \.self gives SwiftUI a way to discriminate between views made from the same stuff
struct ContentView: View {
    let students = ["Vinnie", "Horshack", "Boom Boom", "Epstein"]
    @State private var selectedStudent = "Vinnie"

    var body: some View {
        NavigationStack {
            Form {
                Picker("Select your student", selection: $selectedStudent) {
                    ForEach(students, id: \.self) {
                        Text($0)
                    }
                }
            }
        }
    }
}

Over the last year or so I was making apps in Microsoft PowerApps which are very much data-driven, and each screen is its own thing. I wonder how app views are structured in SwiftUI. I suppose I will find out soon!