Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

698
Views
iOS MapKit - Which overlay was tapped

I am trying to build an app that shows some areas(polygons/overlays) on the map and when a polygon is tapped I would like to print on console print("Polygon \(zone_id) has been tapped"). The polygons are rendered from a GeoJSON file where we can also find the zone_id in the properties feature. So far I rendered the overlays on the map but I am stuck and I appreciate some guidance where to go from here.

I will paste my code that I have so far and also a snippet of the GeoJSON file.

import SwiftUI
import CoreLocation

struct Home: View {
   
  @StateObject var mapData = MapViewModel()
   
  var body: some View {
    ZStack{
       
      MapView()
        .environmentObject(mapData)
        .ignoresSafeArea(.all, edges: .all)
         
    }
  }
}

struct Home_Previews: PreviewProvider {
  static var previews: some View {
    Home()
  }
}
import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {
   
  @EnvironmentObject var mapData: MapViewModel
   
  @State var restrictions: [MKOverlay] = []
   
  func makeCoordinator() -> Coordinator {
    return MapView.Coordinator()
  }
   
  func makeUIView(context: Context) -> MKMapView {
     
    let view = mapData.mapView
     
    view.showsUserLocation = true
    view.delegate = context.coordinator
     
    mapData.showRestrictedZones { (restrictions) in
      self.restrictions = restrictions
      view.addOverlays(self.restrictions)
    }
    return view
  }
   
  func updateUIView(_ uiView: MKMapView, context: Context) {
     
  }
   
  class Coordinator: NSObject, MKMapViewDelegate {
     
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
      if let polygon = overlay as? MKPolygon {
        let renderer = MKPolygonRenderer(polygon: polygon)
        renderer.fillColor = UIColor.purple.withAlphaComponent(0.2)
        renderer.strokeColor = .purple.withAlphaComponent(0.7)
         
        return renderer
      }
      return MKOverlayRenderer(overlay: overlay)
    }
  }
}
import SwiftUI
import MapKit

// All Map Data Goes here...

class MapViewModel: NSObject, ObservableObject {
   
  @Published var mapView = MKMapView()
   
   
  
  // Decode GeoJSON from the server
  func showRestrictedZones(completion: @escaping ([MKOverlay]) -> ()) {
    guard let url = URL(string: "https://flightplan.romatsa.ro/init/static/zone_restrictionate_uav.json") else {
      fatalError("Unable to get geoJSON") }
     
    downloadData(fromURL: url) { (returnedData) in
      if let data = returnedData {
        var geoJson = [MKGeoJSONObject]()
        do {
          geoJson = try MKGeoJSONDecoder().decode(data)
        } catch {
          fatalError("Unable to decode GeoJSON")
        }
        var overlays = [MKOverlay]()
        for item in geoJson {
          if let feature = item as? MKGeoJSONFeature {
            for geo in feature.geometry {
              if let polygon = geo as? MKPolygon {
                overlays.append(polygon)
                 
              }
            }
          }
        }
        DispatchQueue.main.async {
          completion(overlays)
        }
      }
    }
  }
   
  func downloadData( fromURL url: URL, completion: @escaping (_ data: Data?) -> ()) {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
      guard
        let data = data,
        error == nil,
        let response = response as? HTTPURLResponse,
        response.statusCode >= 200 && response.statusCode < 300 else {
        print("Error downloading data.")
        completion(nil)
        return
      }
      completion(data)
    }
    .resume()
  }
}

And here is a snippet of the GeoJSON structure

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "id": "zone_restrictionate_uav.2120",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [
                            24.98812963,
                            44.10877275
                        ],
                        [
                            24.98806588,
                            44.1070722
                        ],
                        [
                            24.98537796,
                            44.10717296
                        ],
                        [
                            24.9854417,
                            44.10887351
                        ],
                        [
                            24.98812963,
                            44.10877275
                        ]
                    ]
                ]
            },
            "geometry_name": "the_geom",
            "properties": {
                "zone_id": "RZ 2120",
                "human_readable_definition": "POLYGON: 440631.5819N 0245917.2667E- 440625.4599N 0245917.0372E- 440625.8227N 0245907.3606E- 440631.9446N 0245907.5901E- 440631.5819N 0245917.2667E",
                "wkt": "POLYGON((24.9881296281 44.1087727458,24.9880658794 44.1070721972,24.9853779561 44.1071729596,24.9854417047 44.1088735083,24.9881296281 44.1087727458))",
                "lower_lim": "GND",
                "upper_lim": "120m AGL",
                "contact": "mailto: aerofoto@mapn.ro",
                "status": "RESTRICTED"
            }
        },
        {
            "type": "Feature",
            "id": "zone_restrictionate_uav.2121",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [
                            26.44760265,
                            44.13453494
                        ],
                        [
                            26.43440247,
                            44.11089351
                        ],
                        [
                            26.38955244,
                            44.1359355
                        ],
                        [
                            26.40275262,
                            44.15957693
                        ],
                        [
                            26.44760265,
                            44.13453494
                        ]
                    ]
                ]
            },
            "geometry_name": "the_geom",
            "properties": {
                "zone_id": "RZ 2121",
                "human_readable_definition": "POLYGON: 440804.3258N 0262651.3695E- 440639.2166N 0262603.8489E- 440809.3678N 0262322.3888E- 440934.4769N 0262409.9094E- 440804.3258N 0262651.3695E",
                "wkt": "POLYGON((26.4476026463 44.1345349397,26.4344024672 44.1108935127,26.3895524427 44.1359355018,26.4027526218 44.1595769288,26.4476026463 44.1345349397))",
                "lower_lim": "GND",
                "upper_lim": "120m AGL",
                "contact": "mailto: aerofoto@mapn.ro",
                "status": "RESTRICTED"
            }
        }
    ],
    "totalFeatures": 339,
    "numberMatched": 339,
    "numberReturned": 339,
    "timeStamp": "2021-08-15T11:39:26.055Z"
}
over 4 years ago · Santiago Trujillo
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!