swiftswiftuiswiftdataobservation

Delete swift object after leaving view


I have a workout application using SwiftData where the user can start a new workout. When clicking the start button, the user is redirected to a new view (CurrentWorkoutView) in which a workout object is instantiated. The user could then save or cancel the workout.

I'm facing 2 problems:

  1. The workout is being instantiated as soon as the app is launched
  2. The workout is not being "dropped" after the user saves/cancels the workout

This is a simplified version of the code:

// HomeView.swift

...

NavigationLink("Start Workout") {
    CurrentWorkoutView()
}

...
// CurrentWorkoutView.swift

@Environment(\.dismiss) var dismiss
@Environment(\.modelContext) var context
    
@Bindable var workout: Workout = Workout()

var body: some View {

    ...

    .toolbar {
        ToolbarItem(placement: .confirmationAction) {
            Button("Save") {
                workout.end = Date.now
                context.insert(workout)
                dismiss()
            }
        }
            
        ToolbarItem(placement: .cancellationAction) {
            Button("Cancel") {
                context.delete(workout)
                try! context.save()
                dismiss()
            }
        }
    }
}

I've tried to set workout as nullable but, because it's bindable, I can't. It has to be bindable to allow for title, description, etc editing.


Solution

  • You should not use @Bindable when it’s the view that owns the object, use State instead here. And with @State we can make the property optional as well

    @State private var workout: Workout?
    

    Create it in onAppear

    .onAppear {
        workout = Workout()
    }
    

    And since the object has not been inserted into the ModelContext you don’t need to delete it either, just set it to nil in the Cancel button action