Detecting touches on MKOverlay in iOS7 (MKOverlayRenderer)

前端 未结 8 1868
灰色年华
灰色年华 2020-12-04 21:58

I have an MKMapView with possibly hundreds of polygons drawn. Using MKPolygon and MKPolygonRenderer as one is suppose to on iOS7.

What I need is a way of acting upon

8条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-04 22:48

    Based on @davidrynn answer i've accomplished a more dynamic and updated result.

    Swift 5

    Subclass MKMapView:

    public class MapView: MKMapView {
    
    public var mapViewProtocol: MapViewProtocol?
    
    public override func touchesEnded(_ touches: Set, with event: UIEvent?) {
    
        if let touch = touches.first {
    
            if touch.tapCount == 1 {
    
                let touchLocation: CGPoint = touch.location(in: self)
                let locationCoordinate: CLLocationCoordinate2D = self.convert(touchLocation, toCoordinateFrom: self)
    
                var mkCircleList: [MKCircle] = self.overlays.compactMap { $0 as? MKCircle }
                mkCircleList = mkCircleList.filter { $0.contains(locationCoordinate) }
                if !mkCircleList.isEmpty {
    
                    self.mapViewProtocol?.didTapMKCircles(self, mkCircleList)
                }
    
                var mkMultiPolygonList: [MKMultiPolygon] = self.overlays.compactMap { $0 as? MKMultiPolygon }
                mkMultiPolygonList = mkMultiPolygonList.filter { $0.contains(locationCoordinate) }
                if !mkMultiPolygonList.isEmpty {
    
                    self.mapViewProtocol?.didTapMKMultiPolygons(self, mkMultiPolygonList)
                }
    
                var mkPolygonList: [MKPolygon] = self.overlays.compactMap { $0 as? MKPolygon }
                mkPolygonList = mkPolygonList.filter { $0.contains(locationCoordinate) }
                if !mkPolygonList.isEmpty {
    
                    self.mapViewProtocol?.didTapMKPolygons(self, mkPolygonList)
                }
    
                var mkMultiPolylineList: [MKMultiPolyline] = self.overlays.compactMap { $0 as? MKMultiPolyline }
                mkMultiPolylineList = mkMultiPolylineList.filter { $0.contains(locationCoordinate) }
                if !mkMultiPolylineList.isEmpty {
    
                    self.mapViewProtocol?.didTapMKMultiPolylines(self, mkMultiPolylineList)
                }
    
                var mkPolylineList: [MKPolyline] = self.overlays.compactMap { $0 as? MKPolyline }
                mkPolylineList = mkPolylineList.filter { $0.contains(locationCoordinate) }
                if !mkPolylineList.isEmpty {
    
                    self.mapViewProtocol?.didTapMKPolylines(self, mkPolylineList)
                }
    
                //TODO
                //var mkTileOverlayList: [MKTileOverlay] = self.overlays.compactMap { $0 as? MKTileOverlay }
                //mkTileOverlayList = mkTileOverlayList.filter { $0.contains(locationCoordinate) }
    
    
                self.mapViewProtocol?.didTapMap(self, locationCoordinate)
            }
        }
    
        super.touchesEnded(touches, with: event)
    }
    

    }

    After that i created multiple extensions for each mkOverlay type:

    MKKCircle

    import Foundation
    import MapKit
    
    extension MKCircle {
    
        func contains(_ coordinate2D: CLLocationCoordinate2D) -> Bool {
    
            let renderer = MKCircleRenderer(circle: self)
            let currentMapPoint: MKMapPoint = MKMapPoint(coordinate)
            let viewPoint: CGPoint = renderer.point(for: currentMapPoint)
            if renderer.path == nil {
    
                return false
            } else {
    
                return renderer.path.contains(viewPoint)
            }
        }
    }
    

    MKMultiPolygon

    import Foundation
    import MapKit
    
    @available(iOS 13.0, *)
    extension MKMultiPolygon {
    
        func contains(_ coordinate2D: CLLocationCoordinate2D) -> Bool {
    
            return self.polygons.filter { $0.contains(coordinate2D) }.isEmpty ? false : true
        }
    }
    

    MKMultiPolyline

        import Foundation
    import MapKit
    
    @available(iOS 13.0, *)
    extension MKMultiPolyline {
    
        func contains(_ coordinate2D: CLLocationCoordinate2D) -> Bool {
    
            return self.polylines.filter { $0.contains(coordinate2D) }.isEmpty ? false : true
        }
    }
    

    MKPolygon

    import Foundation
    import MapKit
    
    extension MKPolygon {
    
        func contains(_ coordinate2D: CLLocationCoordinate2D) -> Bool {
    
            let renderer = MKPolygonRenderer(polygon: self)
            let currentMapPoint: MKMapPoint = MKMapPoint(coordinate2D)
            let viewPoint: CGPoint = renderer.point(for: currentMapPoint)
            if renderer.path == nil {
    
                return false
            } else {
    
                return renderer.path.contains(viewPoint)
            }
        }
    }
    

    MKPolyline

    import Foundation
    import MapKit
    
    extension MKPolyline {
    
        func contains(_ coordinate2D: CLLocationCoordinate2D) -> Bool {
    
            let renderer = MKPolylineRenderer(polyline: self)
            let currentMapPoint: MKMapPoint = MKMapPoint(coordinate2D)
            let viewPoint: CGPoint = renderer.point(for: currentMapPoint)
            if renderer.path == nil {
    
                return false
            } else {
    
                return renderer.path.contains(viewPoint)
            }
        }
    }
    

    And finally create and implement the protocol:

        public protocol MapViewProtocol {
    
        func didTapMKPolygons(_ mapView: MKMapView, _ mkPolygons: [MKPolygon])
    
        func didTapMKCircles(_ mapView: MKMapView, _ mkCircles: [MKCircle])
    
        func didTapMKPolylines(_ mapView: MKMapView, _ mkPolylines: [MKPolyline])
    
        func didTapMKMultiPolygons(_ mapView: MKMapView, _ mkMultiPolygons: [MKMultiPolygon])
    
        func didTapMKMultiPolylines(_ mapView: MKMapView, _ mkMultiPolylines: [MKMultiPolyline])
    
        func didTapMap(_ mapView: MKMapView, _ clLocationCoordinate2D: CLLocationCoordinate2D)
    }
    

提交回复
热议问题