100 Days of SwiftUI

Day 20

2026-05-08

Project 2, part 1

Guess the Flag — learn some of the many flags of the world

Guess the Flag: Introduction

Using stacks to arrange views

  • stacks
    • HStack (horizontal)
    • VStack (vertical)
    • ZStack (depth)
  • even though SwiftUI will show views without a defined nStack, it’s better to be explicit because it will put your view where it wants
  • plus you can style the nStack easier
  • alignment: use .leading and .trailing (instead of left/right) to handle RTL languages
  • H- and V- stacks automatically fit their contents; preferring to align to the center of the view
    • Spacer() will “spring” the stack to the start of the view; you can use multiples of them
  • ZStack has alignment but not Spacer()
    • draws views from top to bottom
  • Stacks can hold other stacks
struct ContentView: View {
    var body: some View {
        HStack (spacing: 20) {
            VStack (spacing: 20) {
                Text("Cell 1")
                Text("Cell 4")
                Text("Cell 7")
            }
            VStack (spacing: 20) {
                Text("Cell 2")
                Text("Cell 5")
                Text("Cell 8")
            }
            VStack (spacing: 20) {
                Text("Cell 3")
                Text("Cell 6")
                Text("Cell 9")
            }
        }
    }
}

Colors and frames

  • lots of ways to handle colors
    • background() modifier only affects text(?)
    • to color the background of the stack, use Color.red before the text (remember the first line is the bottom of the stack)

These are identical:

(1)
  ZStack {
      Text("Your content")
  }
  .background(.red)

(2)

  ZStack {
    Text("Your content")
        .background(.red)
  }

This is interesting: if I use this code, I get green with white edges

ZStack {
    Color(.green)
    Text("Your content")
        }

However, if I use this code, I get something I didn’t quite expect (green with red edges)

ZStack {
    Color(.green)
    Text("Your content")
        }.background(.red)

And if I use this code, I get what I expected from the previous code (green with white edges and text on a small red background)

ZStack {
    Color(.green)
    Text("Your content")
        .background(.red)
        }

Good to know!

  • .frame can restrict the size of the view. In this case the Color(.green) view can be restricted to a specific height and width, have min/max dimensions (including .infinity), etc.
    • this has an effect on how the .background() modifier works too
  • Color() has built in colors but also “semantic” colors (e.g. Color.primary) — useful for light/dark mode switching
  • also can specify in RGBA (Color(red: r, green: g, blue: b, opacity: a))
  • by default it avoids “unsafe” areas: use .ignoreSafeArea() to get the view to the edge (ok for decorative, be careful with functionality)
  • background() can also accept “materials”

Gradients

  • gradients are a way to make stuff ugly fast!
  • requires an array of colors, size & direction, type of gradient
  • you can also put in gradient stops
  • types that can be used as Views: LinearGradient(), RadialGradient(), AngularGradient() (controllable)
  • other type .gradient can be used to modify foregrounds and backgrounds (very subtle)

Buttons and images

  • lots of built in styles. use role: .destructive for example, to get automatic warning coloration
  • can have images
  • Label("text", systemImage:"sf") puts text and image together so Swift can decide how much to show based on context (unlike HStack which will always show both)
  • use Image(decorative:) to hide it from screen readers / voiceover
  • SF Symbols library is available here and comes with an app to explore it

Showing alert messages

  • basic alert has a title and a button to dismiss it
  • we create a state that will be used to show and hide the alert, e.g. @State private var showingAlert = false
  • then we attach it somewhere in the view using a modifier .alert("Important message", isPresented: $showingAlert) { Button(...) }
  • all buttons on the alert will dismiss the alert message