TigrouMeow
TigrouMeow

Reputation: 3779

How to get the MKMapView instance from my UIViewRepresentable view?

I am using MapView this way (the code is of course simplified):

struct IkMapView: UIViewRepresentable {
  var mapView = MKMapView()

  func makeUIView(context: Context) -> MKMapView {
    mapView.delegate = context.coordinator
    return mapView
  }

  public func unselectAllSpots() {
    // mapView is useless and not the actual map view I am seeing
    for annotation in mapView.annotations {
      mapView.deselectAnnotation(annotation, animated: false)
    }
  }

  func updateUIView(_ view: MKMapView, context: Context) {
    // this view is good
  }

  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
    var parent: IkMapView
    
    init(_ parent: IkMapView) {
      self.parent = parent
      super.init()
    }
  }
}

I would like to expose a few public functions to allow actions from the parent view, for example, here, it is the unselectAllSpots() function. However, when I call it from the parent, the mapView is not the same one as the one I get through updateUIView(), and it doesn't actually impact the map. I have read somewhere that the actual displayed mapView is not that instance (but the instance we get in updateUIView().

What's the best way to solve this? I could transform my struct into a class and create a new MKMapView property which I would associate to the map view I get through updateUIView but that doesn't feel right at all.

Thanks a lot for your help :)

Upvotes: 1

Views: 285

Answers (1)

Asperi
Asperi

Reputation: 257493

A representable is updated on changed external states, so a possible approach is to do needed changes on binding changes, like

struct IkMapView: UIViewRepresentable {
    @Binding var unselectAll: Bool       // << activates update

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()        // create here !!
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ mapView: MKMapView, context: Context) {
        if unselectAll {                // << handle state
            for annotation in mapView.annotations {
                mapView.deselectAnnotation(annotation, animated: false)
            }
            unselectAll = false
        }
    }

// .. other code

Upvotes: 2

Related Questions