100 Days of SwiftUI

Day 37

2026-05-26

Project 7, part 2

Building the basic iExpense app.

Starting with the most basic expense coding: name of the item, type — personal or business, and amount

Building a list we can delete from

  • if you move code to another file, for example putting struct and class definitions outside of the ContentView file for neatness, be sure to add import SwiftUI or the compiler will be mad at you
  • remember if you want to enable deletion, the List needs to be powered by a ForEach
  • also, the ForEach is the home of the modifier that calls the deletion code (onDelete(perform: deletionFunction))

Working with Identifiable items in SwiftUI

  • SwiftUI finds it difficult to keep track of items that may have all the same property values
    • you spend amount:5 every day on type:"personal" name:"lunch"
    • SwiftUI needs to know how it can identify each item uniquely
    • List already kinda knows how to handle this, but not everything does
  • you give your struct properties a UUIDlet id = UUID()
  • make the struct conform to Identifiable protocol, e.g. struct ExpenseItem: Identifiable { ... }
    • must have an id parameter
    • adding that means you can remove the id from the ForEach because SwiftUI knows each item is already uniquely identified

Sharing an observed object with a new view

  • classes that use @Observable can be used in more than one view, and the properties can be shared between the views
  • it involves making sure your new View (in a new SwiftUI View file) expects the object, and then passing it to the view when you call it
  • also, you need to give something to the #Preview macro at the bottom of the new view file, such as:
#Preview {
    AddView(expenses: Expenses())
}

Making changes permanent with UserDefaults

  • the UI is functional, but the app doesn’t really work yet, for example, adding expenses does nothing
  • also, saving is only for the current session, so we need to save data between launches of the app
  • this is where we use JSONEncoder stuff. I will be looking this up every. single. time.
  • remember, just because you’ve save it, doesn’t mean it’s available to the app — your code needs to read in the stored data

Let me reiterate: I will be looking this up every. single. time

Final polish

  • the Add Expense view just hangs out after you push “Save”, so we want to dismiss it. You do this with the @Environment keyword
    • “dismissing AddView is done by calling dismiss() on the environment when the time is right”
    • since we have a “Save” button, add dismiss() to its actions

 

Tomorrow we will have the challenge, and I hope some of it is to add the date of the expense 🙃