2014-12-01 11 views
5

Ho un file JSON che contiene circa 2.000 posizioni che ho bisogno di visualizzare sulla mappa quando l'altezza della fotocamera della mappa è inferiore a 750 metri di altezza. Qui è il mio codice corrente:Best practice per più di 2000 annotazioni in MapKit

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) 
    } 
} 

E la vista annotazione delegato:

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 
} 

ho pensato che avrei potuto farla franca solo nascondendo i punti di vista, ma ci vuole un buon 20 secondi prima che l'applicazione risponde ancora dopo aver aggiunto i marcatori, e quindi è impossibile spostare la mappa senza intoppi (scende a circa 5 fotogrammi al secondo).

Quindi, se non riesco a farlo, qual è un approccio migliore? Sto indovinando che controllare se una coppia di coordinate è all'interno dei limiti dello schermo ogni volta che la mappa si muove non funzionerà bene a causa del ritardo (basato sul controllo di 2000 coordinate ogni volta). Qualche idea?

EDIT

Sarà sempre e solo vedere circa 10 annotazioni del 2000 come si deve essere molto ingrandita di vedere qualsiasi. È solo il caso del metodo che uso per trovare rapidamente annotazioni nella regione senza questo orrendo ritardo.

+1

è sicuramente bisogno di utilizzare una sorta di clustering. Significa che ci sarà un numero diverso di pin su diversi livelli di zoom. Dai un'occhiata a questa sessione http://asciiwwdc.com/2011/sessions/111 – mrvn

+0

@marvin No, non penso di aver bisogno di usare il clustering. La quantità massima di punti mostrati sulla mappa in una volta sarà di circa 10 (devi essere molto ingrandita), è solo che ci sono 2000 punti in totale – jskidd3

+0

Perché questa domanda ha un voto negativo? – jskidd3

risposta

4

È possibile aggiungere ~ 1.000 annotazioni a MKMapView facilmente. Date un'occhiata a questo progetto di esempio, che aggiunge 3000:

https://github.com/incanus/PointTest

ci sono diverse cose che potete fare per fare questo lavoro meglio.

  1. Basta usare MKPointAnnotation, allora non c'è bisogno di fornire una visione manualmente.

  2. Se è necessaria una visualizzazione personalizzata, è necessario utilizzare l'identificatore di riutilizzo in modo corretto. Attualmente stai creando una nuova vista per ogni annotazione, quando in realtà potresti riutilizzare correttamente visualizzazioni simili ancora e ancora per prestazioni molto migliori.

  3. Si sta analizzando e aggiungendo le annotazioni nel thread principale dell'interfaccia utente, che influisce sulle prestazioni della risposta al tocco. Vedi il progetto precedente per un modo per farlo in background con Grand Central Dispatch mentre ancora aggiungo effettivamente le annotazioni (tutte in una volta, potrei aggiungere) nel thread principale dell'interfaccia utente.

Non è necessario preoccuparsi se le annotazioni sono sullo schermo o no. MapKit fa questo per te, motivo per cui richiede una vista nel callback delegato e non in anticipo.

Il seguente link non è più valido (ottobre 2017)

Ecco un video di 3000 annotazioni dal vivo su un iPhone 5s:

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

+0

Grazie mille per una risposta così dettagliata. Una cosa, potresti forse dare un esempio di codice o un link per mostrare come usare correttamente l'identificatore di riutilizzo (devo usare la visualizzazione personalizzata)? Non riesco a capirlo. Grazie ancora – jskidd3

2

Mi dispiace, sono troppo nuovo per pubblica un commento, quindi risponderò alla tua domanda sull'uso corretto dell'identificatore di riutilizzo qui.

Che, fondamentalmente, vogliono sostituire:

var pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "point") 

con:

var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("point") 
if pinView != nil { 
    pinView.annotation = annotation; 
} else { 
    pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "point") 
}