Heyman
Heyman

Reputation: 539

Adding over 14000 apple MapKit multipolyline overlays as MKOverlays crashes app

I am trying to add an array of multipolylines as MKOverlay to a map view as show in code below:

import SwiftUI
import MapKit


struct PolylineMapView: UIViewRepresentable {
    
    func makeCoordinator() -> MapViewCoordinator{
        return MapViewCoordinator(self)
    }
    
    func updateUIView(_ view: MKMapView, context: Context){
        view.mapType = MKMapType.standard
    }
    
    func makeUIView(context: Context) -> MKMapView{
        let view = MKMapView(frame: .zero)
        view.delegate = context.coordinator
        
        view.showsUserLocation = true
        view.showsScale = true
        view.showsCompass = true
        view.setUserTrackingMode(MKUserTrackingMode.followWithHeading, animated: true)
        
        let overlays: [MKOverlay] = [MKOverlay]() // this overlay will contain 27,000 overlays
        view.addOverlays(overlays)
        
        return view
    }
}

// MARK: -  Coordinator
class MapViewCoordinator: NSObject, MKMapViewDelegate {
    var parent: PolylineMapView
    
    
    init(_ parent: PolylineMapView) {
        self.parent = parent
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        
        if let multiPolyline = overlay as? MKMultiPolyline{
            let polylineRenderer = MKMultiPolylineRenderer(multiPolyline: multiPolyline)
                polylineRenderer.strokeColor = .magenta
            
            polylineRenderer.lineWidth = 2
            polylineRenderer.shouldRasterize = true
            return polylineRenderer
        }
        
        return MKOverlayRenderer(overlay: overlay)
    }
}

The issue I face while adding the huge number of overlays at a time is that the app runs out of memory and crashes. My question is how can I add the overlays only in the mapRect that is visible in order to avoid adding all at once? What is the best way to handle this? It would also be interesting to know how to only render the overlays at a certain zoom level on the map.

Upvotes: 1

Views: 374

Answers (2)

Gerd Castan
Gerd Castan

Reputation: 6849

Only add overlays that make sense at the moment:

MKOverlay has a method that tells you if it intersects with a MKMapRect.

let isVisible = overlay.intersects(mapView.boundingMapRect)

Then add only those overlays that intersect.

If there are still too many overlays left, you can use.

let visible = mapView.boundingMapRect.contains(overly.boundingMapRect)

If you zoom out, you might have to choose which are the most important polylines and show only those.

If this works: write a diff algorithm:

It is probably a bad idea to remove all previous overlays and add all new ones after the region of the mapView changes.

Instead, remove all overlays from mapView that aren't shown any more, add the new overlays, and don't change the overlays that are part of the old and new mapView region.

One more idea: you could merge multiple MKMultiPolyline objects that are near each other (and share the same color...) into one MKMultiPolyline. This can be combined with the idea above.

Upvotes: 0

Fahim Parkar
Fahim Parkar

Reputation: 31627

Adding over 14000 apple MapKit - You are going beyond limit. There is limit set to everything.

To avoid the issue, do below steps.

  1. Show only overlay which are visible to the current region but not to exceed 50. If they are more then 50, show note on the map that "Zoom in to see more properties"

  2. Once user zoom in, based on the region of the visible map, repeat step 1.

Check Zillow app for the same.

https://apps.apple.com/us/app/zillow-real-estate-rentals/id310738695

Upvotes: 0

Related Questions