Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for 2000+ annotations in MapKit

I have a JSON file which contains around 2,000 locations that I need to display on the map when the map camera altitude is less than 750 metres high. Here is my current code:

func addStops() {
    var path: String! = NSBundle.mainBundle().pathForResource("stops", ofType: "json")
    var jsonData: NSData! = NSData(contentsOfFile: path)
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
    self.busStops = jsonResult["results"] as NSArray

    for (var i = 0; i < self.busStops.count; i++) {
        let lat = self.busStops[i]["latitude"] as NSString
        let lng = self.busStops[i]["longitude"] as NSString

        var annotation = busAnno()
        annotation.setCoordinate(CLLocationCoordinate2DMake(CLLocationDegrees(lat.doubleValue), CLLocationDegrees(lng.doubleValue)))
        annotation.type = "stop"
        self.mapView.addAnnotation(annotation)
    }
}

And the annotation view delegate:

func mapView (mapView: MKMapView!, viewForAnnotation annotation: MKPointAnnotation!) -> busMarker! {
    var pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "point")
    pinView.location = annotation.location
    pinView.hidden = true
    pinView.layer.hidden = true
    pinView.enabled = false
}

I thought I could get away with just hiding the views, but it takes a good 20 seconds before the application even responds after adding the markers, and then it's impossible to move the map around smoothly (drops to about 5 frames per second).

So if I can't do that, what is a better approach? I'm guessing that checking if a pair of coordinates is within the screen's bounds every time the map moves won't work well due to lag (based on checking 2000 coordinates every time). Any ideas?

EDIT

You will only ever see about 10 annotations of the 2000 as you have to be very zoomed in to see any. It's just a case of which method I use to quickly find annotations in the region without this horrendous lag.

like image 309
jskidd3 Avatar asked Dec 01 '14 17:12

jskidd3


People also ask

What is MapKit span?

The "span" in this class refers to the width and height of a region, with distances expressed in degrees of latitude and longitude.

How do I use MapKit in swift 5?

Go to the storyboard. Drag a MapKit View to the main View. Give the MapKit View the same size as the main View. Select the MapKit View and go to the Pin button from the Auto Layout button on the bottom-right of the Storyboard and fill in the following values.

What is MapKit framework?

Overview. Use MapKit to give your app a sense of place with maps and location information. You can use the MapKit framework to: Embed maps directly into your app's windows and views. Add annotations and overlays to a map to call out points of interest.


1 Answers

You can add ~1,000 annotations to an MKMapView easily. Take a look at this sample project, which adds 3,000:

https://github.com/incanus/PointTest

There are several things you can do to make this work better.

  1. Just use MKPointAnnotation, then you don't have to provide a view manually.

  2. If you do need a custom view, you should use the reuse identifier properly. You are currently creating a new view for every annotation, when in actuality you could be properly reusing similar views again and again for much greater performance.

  3. You are parsing and adding your annotations in the main UI thread, which impacts touch response performance. See the above project for a way to do this in the background with Grand Central Dispatch while still actually adding the annotations (all at once, I might add) in the main UI thread.

You don't need to worry about whether annotations are on screen or not. MapKit does this for you, which is why it queries for a view in the delegate callback and not upfront.

The following link is no longer valid (Oct 2017)

Here's a video of 3,000 annotations live on an iPhone 5s:

https://dl.dropboxusercontent.com/u/575564/3000points.mov

like image 131
incanus Avatar answered Nov 03 '22 10:11

incanus