Guard every persisted read of retained workout models with isLive

A remotely deleted @Model traps on any persisted-property read, including
the observed expression of .onChange, which SwiftUI evaluates on every
body pass. Guard those expressions, the onAppear takeover read, and the
summary sheet's document mapping.

Claude-Session: https://claude.ai/code/session_01PKptrgbx74peTwHGRxBojv
This commit is contained in:
2026-07-12 00:37:05 -04:00
parent 8854ad59d5
commit 7b6c39d8f0
4 changed files with 38 additions and 21 deletions
@@ -112,10 +112,12 @@ struct WorkoutLogListView: View {
// ingesting our latest edit) must not regress what the user is looking
// at. Clock skew across devices degrades this to a skipped absorb
// never to a clobber of local state.
.onChange(of: workout.updatedAt) { _, incoming in
// ...but never absorb from an entity a push has just deleted: mapping a
// deleted @Model traps.
if incoming > doc.updatedAt, let fresh = WorkoutDocument(fromLive: workout) {
.onChange(of: workout.isLive ? workout.updatedAt : nil) { _, incoming in
// ...and never absorb from an entity a push has just deleted: the observed
// expression above is evaluated on every body pass, so even it must be
// liveness-guarded reading a persisted property on a dead @Model traps.
if let incoming, incoming > doc.updatedAt,
let fresh = WorkoutDocument(fromLive: workout) {
doc = fresh
}
}