swiftswiftui

Can I use an ObservedObject inside a Coordinator?


I have a MapView using MKMapView, and I have a HomeView which shows the MapView and ResultsCarouselView (for now just replacing it with Circle for ease).

If I have an observable object to manage the state for this HomeView, is it possible to use this from the coordinator? For example, anything I call from HomeState in the coordinator does not update HomeView:

MapCoordinator

final class MapCoordinator: NSObject, MKMapViewDelegate {
  @ObservedObject var homeState = HomeState()

  // other code, init, etc.

  func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
    self.homeState.setUserLocated(true)
  }
}

HomeState:

class HomeState: NSObject, ObservableObject {
  @Published var userLocated = false

  func setUserLocated(_ value: Bool) {
    self.userLocated = value // debugger comes here, but is this another instance or something?
  }
}

HomeView:

struct HomeView: View {
  @ObservedObject var homeState = HomeState()
  
  var body: some View {
    ZStack(alignment: .bottom) {
      MapView()

      if (homeState.userLocated) {
         Circle()   // this doesn't show up
      }
    }
  }
}

Solution

  • struct MapView: UIViewRepresentable {
    @StateObject var homeState = HomeState()
    
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        return mapView
    }
    
    func updateUIView(_ view: MKMapView, context: Context) {
    
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
    
        init(_ parent: MapView) {
            self.parent = parent
        }
    
        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            self.parent.homeState.setUserLocated(true)
        }
    }
    }
    

    You use the parent variable in the Coordinator to modify any @State or @ObservableObject such as your HomeState @ObservedObject