Is there a way to reload a swiftUI view from its hosting controller?
I have a WKHostingController with a swiftUI view for its body. When notification outside of the view gets fired, I need to update the view. If I try to change a @Binding or @State variable, I'm getting error
I can't update values outside of the view
But I can't find a refresh method.
Any ideas?
Hosting Controller:
class WorkoutListInterfaceController : WKHostingController<WorkoutListView> {
override var body: WorkoutListView {
WorkoutListView(host: self)
}
override func didAppear() {
// update WorkoutListView!!!
}
func showExercises(forWorkout workout: Workout) {
WKInterfaceController.reloadRootControllers(withNamesAndContexts: [(name: "ExerciseListInterfaceController", context: workout as AnyObject)])
}
func showAddWorkout() {
presentController(withNamesAndContexts: [("AddWorkoutHostingController", context: "" as AnyObject)])
}
}
SwiftUI View:
struct WorkoutListView : View {
weak var host: WorkoutListInterfaceController?
@State private var shouldPresentAddWorkout = false
@State var workouts: [Workout] = Workout.all()
init(host: WorkoutListInterfaceController) {
self.host = host
}
var body: some View {
return List {
Section(header: Text("Workouts")
.font(.system(size: 18))
.fontWeight(.bold)
.frame(height: 18))
{
ForEach(workouts) { workout in
Button(action: {
self.host?.showExercises(forWorkout: workout)
}) {
Text(workout.title)
}
}
}
Button(action: {
self.host?.showAddWorkout()
}) {
Text("Add Workout")
.fontWeight(.medium)
.foregroundColor(.green)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
}
}
.sheet(isPresented: $shouldPresentAddWorkout, onDismiss: {}) {
AddWorkoutView(host: AddWorkoutHostingController())
}
.contextMenu {
Button(action: { self.host?.showAddWorkout() },
label: {
VStack {
Image(systemName: "plus")
Text("Add Workout")
}
})
}
}
}
WorkoutListInterfaceController
's didAppear()
gets called and I want to update WorkoutListView
.
On onAppear()
, swiftUI view modifier doesn't get called. I don't know if this is a bug or expected behavior, that's why I am defaulting to the didAppear()
on the hosting controller to refresh the view.
Got this to work with using Combine and NotificationCenter by posting a notification when the presented view will dismiss:
NotificationCenter.default.post(name: .updateWorkoutsNotification, object: workouts)
And then subscribing to that notification in a WorkoutListView view model