I'm working in SwiftUI and using MKMapView to show a map, annotations, and overlays on a view.
I was using the new Map()
but the lack of overlay support has pulled me back to UIKit Representable.
When I was using Map
it was easy to add annotations, but when using UIKitRepresentable
I'm a bit confused on where to put the data, and how to make annotations from an array pulled from a network call.
Everything I've read has been either in Obj-C or adding a single annotation point. I'm trying to add (at present ~800) which is why I wanted to take advantage of the MKMapView in its reusability and clustering.
This is what I have at the moment:
struct UIMapView: UIViewRepresentable {
@EnvironmentObject var dataModel: DataModel
@EnvironmentObject var mapViewModel: MapViewModel
func makeCoordinator() -> Coordinator { Coordinator() }
func makeUIView(context: Context) -> MKMapView {
let view = mapViewModel.mapView
drawOverlayRing(view: view)
view.delegate = context.coordinator
return view
}
func updateUIView(_ uiView: MKMapView, context: Context) {}
class Coordinator: NSObject, MKMapViewDelegate {
func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
let identifier = "pinAnnotation"
var annotationView = map.dequeueReusableAnnotationView(
withIdentifier: identifier
) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(
annotation: annotation,
reuseIdentifier: identifier
)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
func getAnnotations(view: MKMapView) {
for location in dataModel.locations {
let annotation = MKPointAnnotation()
annotation.title = location.title
annotation.coordinate = CLLocationCoordinate2D(
latitude: location.latitude,
longitude: location.longitude
)
view.addAnnotation(annotation)
}
}
}
I sometimes put my annotations in updateUIView, something like this:
func updateUIView() {
// remove the old ones
uiView.removeAnnotations(uiView.annotations)
uiView.addAnnotations(toMapAnnotations(locations: dataModel.locations))
}
func toMapAnnotations(locations: [CLLocationCoordinate2D]) -> [MapAnnotation] {
return locations.map { MapAnnotation(location: $0) }
}
final class MapAnnotation: NSObject, MKAnnotation {...}