I am using SwiftUI and UIViewRepresentable to display a map with different coloured MKPolygons as well as MKAnnotations.
While I can get the polygons to render correctly, I cannot get more than one annotation to load at a time. I think it has something to do with the way I am calculating the value of 'landmarks' as it's only reading a single line of the data array, but having trouble figuring out another way to calculate this.
I intend to add more polygons and annotations so looking for a scaleable solution and hoping my current approach is somewhat in the right direction.
My code as follows: (I'm a beginner so apologies if the approach I'm taking is ugly!)
import SwiftUI
import MapKit
fileprivate class BlueSector: MKPolygon {
}
fileprivate class RedSector: MKPolygon {
}
fileprivate class MapPins: NSObject, MKAnnotation {
let title: String?
let subtitle: String?
let coordinate: CLLocationCoordinate2D
init(title: String?,
subtitle: String?,
coordinate: CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
}
}
struct MapView: UIViewRepresentable {
let region: MKCoordinateRegion
let todCoordinates: [CLLocationCoordinate2D]
let oplCoordinates: [CLLocationCoordinate2D]
let mapPoints: [(title: String, subtitle: String, coordinate: CLLocationCoordinate2D)]
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
mapView.region = region
let todpolygon = BlueSector(coordinates: todCoordinates, count: todCoordinates.count)
mapView.addOverlay(todpolygon)
let oplpolygon = RedSector(coordinates: oplCoordinates, count: oplCoordinates.count)
mapView.addOverlay(oplpolygon)
let landmarks = MapPins(title: mapPoints[0].0, subtitle: mapPoints[0].1, coordinate: mapPoints[0].2)
mapView.addAnnotation(landmarks)
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, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let routePolyline = overlay as? MKPolygon {
let renderer = MKPolygonRenderer(overlay: routePolyline)
if overlay is BlueSector {
renderer.strokeColor = UIColor.systemBlue
renderer.lineWidth = 2
renderer.fillColor = UIColor.systemCyan
renderer.alpha = 0.5
} else {
renderer.strokeColor = UIColor.systemRed
renderer.lineWidth = 2
renderer.fillColor = UIColor.systemPink
renderer.alpha = 0.5
}
return renderer
}
return MKOverlayRenderer()
}
func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "pinAnnotation"
var annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
}
annotationView?.annotation = annotation
return annotationView
}
}
struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: -24.1500, longitude: 133.2500),
span: MKCoordinateSpan(latitudeDelta: 50, longitudeDelta: 50)
)
// BLUE POLYGON COORDINATES
@State private var todCoordinates = [
CLLocationCoordinate2D(latitude: -23.1902, longitude: 127.0806),
CLLocationCoordinate2D(latitude: -24.2905, longitude: 128.0645),
CLLocationCoordinate2D(latitude: -26.0708, longitude: 128.0648),
CLLocationCoordinate2D(latitude: -28.4816, longitude: 130.4419),
CLLocationCoordinate2D(latitude: -28.4826, longitude: 130.4852),
CLLocationCoordinate2D(latitude: -28.1001, longitude: 131.3645),
CLLocationCoordinate2D(latitude: -30.2052, longitude: 133.5951),
CLLocationCoordinate2D(latitude: -29.0006, longitude: 136.4946),
CLLocationCoordinate2D(latitude: -28.0017, longitude: 137.5943),
CLLocationCoordinate2D(latitude: -26.1314, longitude: 138.2312),
CLLocationCoordinate2D(latitude: -22.1747, longitude: 136.3819),
CLLocationCoordinate2D(latitude: -21.5143, longitude: 136.2242),
CLLocationCoordinate2D(latitude: -21.2947, longitude: 136.1949),
CLLocationCoordinate2D(latitude: -21.1201, longitude: 131.5020),
CLLocationCoordinate2D(latitude: -23.1304, longitude: 128.2753),
CLLocationCoordinate2D(latitude: -23.1902, longitude: 127.0806),
];
// RED POLYGON COORDINATES
@State private var oplCoordinates = [
CLLocationCoordinate2D(latitude: -30.2052, longitude: 133.5951),
CLLocationCoordinate2D(latitude: -29.0006, longitude: 136.4946),
CLLocationCoordinate2D(latitude: -28.0017, longitude: 137.5943),
CLLocationCoordinate2D(latitude: -26.1314, longitude: 138.2312),
CLLocationCoordinate2D(latitude: -28.5948, longitude: 143.3004),
CLLocationCoordinate2D(latitude: -29.5342, longitude: 142.4100),
CLLocationCoordinate2D(latitude: -31.0006, longitude: 142.4837),
CLLocationCoordinate2D(latitude: -31.4744, longitude: 143.3102),
CLLocationCoordinate2D(latitude: -33.0014, longitude: 143.3050),
CLLocationCoordinate2D(latitude: -33.2030, longitude: 140.3420),
CLLocationCoordinate2D(latitude: -33.0506, longitude: 140.1330),
CLLocationCoordinate2D(latitude: -32.5153, longitude: 139.4819),
CLLocationCoordinate2D(latitude: -31.3500, longitude: 138.5950),
CLLocationCoordinate2D(latitude: -31.3456, longitude: 135.2446),
CLLocationCoordinate2D(latitude: -30.2052, longitude: 133.5951),
];
// ANNOTATION DATA FOR BOTH POLYGONS
@State private var mapPoints = [
(title: "TOD",
subtitle: "Tod",
coordinate: CLLocationCoordinate2D(latitude: -23.6980, longitude: 133.8807)),
(title: "OPL",
subtitle: "Opal",
coordinate: CLLocationCoordinate2D(latitude: -30.5929, longitude: 138.4039)),
];
var body: some View {
MapView(
region: region,
todCoordinates: todCoordinates,
oplCoordinates: oplCoordinates,
mapPoints: mapPoints
)
.edgesIgnoringSafeArea(.top)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}