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.
The "span" in this class refers to the width and height of a region, with distances expressed in degrees of latitude and longitude.
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.
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.
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.
Just use MKPointAnnotation
, then you don't have to provide a view manually.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With