Money Counter Helper (iOS 26+) A modern, highly resilient till-counting application built strictly with modern SwiftUI guidelines. It is designed to track loose change, bills, and rolled coins, automatically calculate deposits against a starting float, and persist data across app launches using SwiftData and UserDefaults caching. ✨ Features • Loose & Roll Tracking: Distinct sections for loose denominations (green) and coin rolls (red). • Starting Float & Deposit Math: Enter a starting float, and the app automatically calculates your expected deposit or cash shortage. • Aggressive Auto-Caching: Every single tap or number entry is instantly saved to UserDefaults. If the app crashes or is swiped away, your exact count is restored upon reopening. • Session Notes: A built-in scratchpad for the current count. Features custom keyboard toolbar buttons to instantly inject the time, total, and float discrepancy into the text. • Count History: Save snapshots of your counts natively using SwiftData. View past counts, check over/short metrics, or swipe to "Resume" a past count directly back into the main calculator. • Native Keyboard Handling: Includes interactive swipe-to-dismiss and a dedicated "Done" button on the numeric keyboard. 🏗 Architecture: How the Files Interact This app uses modern Swift data flow. Instead of passing static variables back and forth, the app relies on Observation (@Observable) for live memory and SwiftData for permanent storage. Here is how each file reads from and communicates with the others: 1. MoneyCounterApp.swift (The Entry Point) • What it does: This is where the app launches. • How it connects: It wraps ContentView and attaches .modelContainer(for: SavedCount.self). This is a crucial step—it tells the entire app environment that SwiftData exists and makes the database available to any file that asks for it. 2. Models.swift (The Database Schema) • What it does: Defines the blueprint for what a "Saved History" item looks like. • How it connects: It defines the @Model class SavedCount. This does not hold live UI data; it acts as the strict template that ContentView uses when writing to the database, and that HistoryView uses when reading from the database. 3. MoneyCounterViewModel.swift (The Brain) • What it does: Handles all the math, stores the arrays of denominations, and manages the UserDefaults background caching. • How it connects: It is marked with the modern @Observable macro. This means it acts like a live broadcast station. When ContentView creates an instance of it, the view automatically "listens" to it. If the ViewModel calculates a new total, ContentView instantly redraws without needing to be manually told to update. 4. ContentView.swift (The Main UI) • What it does: Displays the scrolling list of coins/bills and the bottom totals bar. • How it connects: * Reads from ViewModel: Uses @State private var viewModel to read the live totals and write button taps back to the ViewModel. • Reads from AppStorage: Uses @AppStorage to hold the session notes string. This acts as an invisible bridge to the device's hard drive so the text survives app closures. • Writes to SwiftData: It accesses the database provided by MoneyCounterApp using @Environment(\.modelContext). When you save a session, it packages the ViewModel's current numbers into a SavedCount model and pushes it into this context. • Passes to Sub-Views: It opens NotesView and HistoryView as .sheet overlays, passing down the necessary references so they can see the same data. 5. NotesView.swift (The Sub-View for Text) • What it does: Displays the text editor for shift notes. • How it connects: It receives data from ContentView in two ways: • @Binding var notes: It binds directly to the @AppStorage string in ContentView. Typing here actually edits the variable living inside ContentView. • Constants (let total, let discrepancy): ContentView passes the current math totals down as read-only constants so NotesView can inject them into the text via its keyboard shortcut buttons. 6. HistoryView.swift (The SwiftData Reader) • What it does: Displays the list of previously saved counts. • How it connects: * Reads from SwiftData: Uses the @Query macro to automatically look into the database (set up by MoneyCounterApp) and fetch all SavedCount items, sorting them by date. • Writes to ViewModel: When you swipe and tap "Resume", HistoryView takes the saved snapshot and pushes it directly into the MoneyCounterViewModel instance passed to it by ContentView. This instantly overwrites the live calculator with the historical data.