I have an app architecture similar to the below (simplified) code. I use a WorkoutManager
StateObject
which I initialize in the set up view, then pass down to its children via EnvironmentObject
. The problem is that upon dismissing the .sheet
there isn't any life cycle event which initializes a new WorkoutManager
, which I need in order to be able to start new workouts consecutively. How in this example below can I give WorkoutView
the ability to reinitialize WorkoutManager so that it is a clean object?
import SwiftUI
import HealthKit
class WorkoutManager: ObservableObject {
var workout: HKWorkout?
}
struct ContentView: View {
@StateObject var workoutManager = WorkoutManager()
@State var showingWorkoutView = false
var body: some View {
Button {
showingWorkoutView.toggle()
} label: {
Text("Start Workout")
}
.sheet(isPresented: $showingWorkoutView) {
WorkoutView(showingWorkoutView: $showingWorkoutView)
}
}
}
struct WorkoutView: View {
@EnvironmentObject var workoutManager: WorkoutManager
@Binding var showingWorkoutView: Bool
var body: some View {
Text("Workout Started")
.padding()
Button {
showingWorkoutView.toggle()
//Here I want to initialize a new WorkoutManager to clear out the previous workout's state, how?
} label: {
Text("End Workout")
}
}
}
CodePudding user response:
As mentioned in the comments already, the route you probably want to take is reseting the state within the same WorkoutManager
. You wouldn't be able to assign a new object to a @StateObject
anyway -- you'll end up with compiler errors because of the View
's immutable self
.
Secondly, I'd suggest that you probably don't want to rely on the Button
in your WorkoutView
to do this. For example, if the user dismissed the sheet
by swiping, that wouldn't get called. Instead, you could listen for the sheet
's state in onChange
(another method would be using the onDismiss
parameter of sheet
):
class WorkoutManager: ObservableObject {
var workout: HKWorkout?
func resetState() {
//do whatever you need to do to reset the state
print("Reset state")
}
}
struct ContentView: View {
@StateObject var workoutManager = WorkoutManager()
@State var showingWorkoutView = false
var body: some View {
Button {
showingWorkoutView.toggle()
} label: {
Text("Start Workout")
}
.sheet(isPresented: $showingWorkoutView) {
WorkoutView(showingWorkoutView: $showingWorkoutView)
}
.onChange(of: showingWorkoutView) { newValue in
if !newValue {
workoutManager.resetState()
}
}
}
}
struct WorkoutView: View {
@EnvironmentObject var workoutManager: WorkoutManager
@Binding var showingWorkoutView: Bool
var body: some View {
Text("Workout Started")
.padding()
Button {
showingWorkoutView.toggle()
} label: {
Text("End Workout")
}
}
}