The repository pattern
Views and view models shouldn't know where data lives
Every view model you've written talks straight to APIClient.shared. Add SwiftData and there's a second thing to talk to β ModelContext β and a naive view model ends up juggling both: fetch from the network, insert into the context, query the context, handle the case where one works and the other doesn't. That's a lot of concerns tangled into one type, and it's untestable without a real network and a real database.
The fix is a seam: a WalkRepository protocol that hides both ModelContext and APIClient behind a handful of methods. The view model calls the protocol; it never imports SwiftData or knows an API exists. Two things fall out of that for free: you can swap in a fake repository in tests (no network, no database, just canned data), and you can swap the real backend later β REST today, GraphQL next year β without touching a single view.