2009-09-05 12 views
15

sto risparmiando mappa regione in default utente quando la mia applicazione per iPhone si sta chiudendo in questo modo:MKMapView erroneamente visualizzata salvato regione

MKCoordinateRegion region = mapView.region; 
[[NSUserDefaults standardUserDefaults] setDouble:region.center.latitude forKey:@"map.location.center.latitude"]; 
[[NSUserDefaults standardUserDefaults] setDouble:region.center.longitude forKey:@"map.location.center.longitude"]; 
[[NSUserDefaults standardUserDefaults] setDouble:region.span.latitudeDelta forKey:@"map.location.span.latitude"]; 
[[NSUserDefaults standardUserDefaults] setDouble:region.span.longitudeDelta forKey:@"map.location.span.longitude"]; 

Quando app lancia ancora una volta, Ш leggere quei valori indietro allo stesso modo, in modo che il utente può vedere esattamente la stessa guarda la mappa come è stato l'ultima volta:

MKCoordinateRegion region; 

region.center.latitude = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.latitude"]; 
region.center.longitude = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.longitude"]; 
region.span.latitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"]; 
region.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"]; 

NSLog([NSString stringWithFormat:@"Region read : %f %f %f %f", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta]); 

[mapView setRegion:region]; 

NSLog([NSString stringWithFormat:@"Region on map: %f %f %f %f", mapView.region.center.latitude, mapView.region.center.longitude, mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta]); 

la regione che ho letto da impostazioni predefinite dell'utente è (non a caso) esattamente la stessa di quando è stato salvato. Nota che ciò che viene salvato viene direttamente dalla mappa, quindi non viene trasformato in alcun modo. Lo rimetto sulla mappa con il metodo setRegion:, ma poi è diverso!

risultati Esempio:

Region read : 50.241110 8.891555 0.035683 0.042915<br> 
Region on map: 50.241057 8.891544 0.050499 0.054932 

Qualcuno sa perché questo accade?

+0

Ho trovato una soluzione per ottenere esattamente la regione della mappa che desideri: vedere il mio post su http://stackoverflow.com/questions/3612007/mkmapview-setregion-snaps-to-predefined-zoom-levels/7935 – AlexWien

risposta

2

Ho avuto lo stesso problema. Questo è molto frustrante. Sembra che la documentazione di MKMapView non sia corretta in alcune aree relative ai tipi di dati.

Se si impostano i parametri della regione come (doppio) s si otterrà l'errore che si sta avendo. Tuttavia, se i parametri della regione vengono passati (float) si otterrà il comportamento corretto.

in modo da provare

MKCoordinateRegion region = {{0.0f,0.0f},{0.0f,0.0f}}; 

region.center.latitude = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.latitude"]; 
region.center.longitude = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.center.longitude"]; 
region.span.latitudeDelta = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"]; 
region.span.longitudeDelta = (float) [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"]; 

mapView.region = region; 
+0

Grazie per La tua risposta. Ho provato a risolvere il mio problema in questo modo, ma ancora non ho fortuna ... Sono abbastanza sicuro che il problema è il troncamento del doppio del float, ma per ora non ho idea di come risolverlo. Qualcun altro per favore? –

0

non posso verificare che questo funziona. Qualcun altro può farlo? Sarei disposto a scommettere che quello che stai vedendo è l'effetto del troncamento dei tuoi sosia nei galleggianti. In alcuni casi, quando ciò accade a me, ho scoperto che posso moltiplicare lo span di 0,9999 e resettare la regione, e quindi sarà quello che voglio. Ma non tutte le regioni - a volte è molto diverso, fino al 20% diverso, specialmente per le campate più piccole.

+0

, mi dispiace - questo è legato al commento qui sotto che inizia con: "Ho avuto lo stesso problema, è molto frustrante ..." – Colin

8

Il problema qui è quando si imposta la regione, il livello di zoom della mappa "scatta" fino alla soglia di zoom più vicina. (Sospetto che queste soglie di zoom siano la quantità di zoom che si ottiene quando si tocca due volte o si tocca due dita)

Quindi, se la mappa mostra il livello di zoom 1 ad esempio, e si imposta la regione su quella stessa distanza valore in tal modo: region = [mapView region]; [mapView setRegion:region]; "scatterà" al livello di zoom più vicino sopra il livello livello 1, ovvero al livello 2 e verrà eseguito lo zoom indietro di circa un fattore due.

La soluzione alternativa per il poster originale è di ridurre leggermente i valori di span prima di impostare la regione, in modo che quando scatta la vista, scatta verso il livello di zoom su cui si trovava, non quello sopra.

ad es.

region.span.latitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.latitude"] * 0.999;

region.span.longitudeDelta = [[NSUserDefaults standardUserDefaults] doubleForKey:@"map.location.span.longitude"] * 0.999;

Se l'utente aveva lo zoom con doppi sfioramenti (e quindi saltare da soglia a soglia) funziona abbastanza bene, riportandoli la stessa vista quasi esattamente.

Tuttavia, se eseguono il pinch-zoom e la vista si trova a metà strada tra le soglie di zoom, continuerà a passare al livello successivo. Non è così buono in quel caso, ma non c'è ancora una soluzione.

Ci sono bug aperti sul radar Apple per questo, si spera che verrà risolto in una versione futura.

+0

Non è un bug. È ben documentato e si comporta esattamente come documentato.https://developer.apple.com/library/iOS/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html – Frizlab

+0

@frizlab il collegamento è morto a cosa stava puntando? – 3366784

+0

@ 3366784 https://developer.apple.com/documentation/mapkit/mkmapview. Ad ogni modo il commento è obsoleto, ora il 'MKMapView' funziona come previsto. – Frizlab

2

OK, quindi ho avuto a che fare con questo problema da un po 'di tempo e penso di aver trovato una soluzione efficace ispirata alla teoria di Crufty (MKMapView show incorrectly saved region). Fondamentalmente, se si imposta la regione di visualizzazione della mappa con i valori recuperati da NSUserDefaults dopo che la vista mappa ha eseguito il caricamento iniziale (completo di comportamento di "snap out"), la regione della mappa sarà quella che ci si aspetterebbe che fosse . Il trucco è trovare un aggancio nel codice dell'applicazione da qualche parte a valle rispetto alla vista mappa che è stata inizializzata. Non carina, ma funziona perfettamente per me. Grazie a Crufty per l'intuizione.

0

Ho riscontrato un maggiore successo utilizzando un fattore di moltiplicazione di 0,9 anziché 0,999 ma a volte si spinge, ma sembra avvicinarsi allo zoom desiderato. Mi piacerebbe ancora risolvere questo problema solo per dire che l'ho battuto! haha

-1

Se si imposta il MapView in InterfaceBuilder, assicuratevi di non fate questo:

_mapView = [[MKMapView alloc] init]; 

Appena ho rimosso questa linea init, il mio guarda la mappa improvvisamente ha cominciato rispondendo correttamente a tutti gli aggiornamenti L'ho mandato. Sospetto che ciò che accade sia che se si esegue l'allocazione init, in realtà sta creando un'altra vista che non viene mostrata da nessuna parte. Quello che vedi sullo schermo è quello inizializzato dal tuo pennino. Ma se ne assegnate uno nuovo, allora è qualcosa da qualche altra parte e non farà nulla.

0

Prova anche per memorizzare atteggiamento simile

self.lastCameraAtitude = self.mapView.camera.altitude; 

e quando u configurare la vostra mappa

[self.mapView.camera setAltitude:self.lastCameraAtitude]; 

Questo imposterà per regione stessa stessa telecamera. Nel tuo caso, imposta solo la regione ma non la fotocamera.

0

Ecco un'estensione Swift per codificare e decodificare correttamente MKCoordinateRegion:

extension MKCoordinateRegion { 

    var encode:[String: AnyObject] { 
     return ["center": 
        ["latitude": self.center.latitude, 
        "longitude": self.center.longitude], 
       "span": 
        ["latitudeDelta": self.span.latitudeDelta, 
        "longitudeDelta": self.span.longitudeDelta]] 
    } 

    init?(decode: [String: AnyObject]) { 

     guard let center = decode["center"] as? [String: AnyObject], 
      let latitude = center["latitude"] as? Double, 
      let longitude = center["longitude"] as? Double, 
      let span = decode["span"] as? [String: AnyObject], 
      let latitudeDelta = span["latitudeDelta"] as? Double, 
      let longitudeDelta = span["longitudeDelta"] as? Double 
     else { return nil } 


     self.center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 
     self.span = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta) 
    } 
} 

Ecco come usarlo:

// Save 
NSUserDefaults.standardUserDefaults().setObject(mapView.region.encode, forKey: "mapRegion01") 

// Restore 
if let dict = NSUserDefaults.standardUserDefaults().dictionaryForKey("mapRegion01"), 
    let myRegion = MKCoordinateRegion(decode: dict) { 

    // do something with myRegion 
} 
0

Recentemente mi ha colpito la stessa cosa. Utilizzando le intuizioni dalle risposte precedenti, il seguente rapida implementazione 4 funziona per me:

override func viewWillAppear(_ animated: Bool) { 
    if isMovingToParentViewController { 
     setInitialRegion() 
     DispatchQueue.main.asyncAfter(deadline: .now(), execute: { 
      self.setInitialRegion() 
     }) 
    } 
} 

Questa imposta una regione di zoom iniziale quando il controllore guarda la mappa viene spinto in vista. La chiamata sincrona a setInitialRegion imposterà una regione a un livello di zoom. La chiamata asincrona a setInitialRegion imposterà la regione esatta. La chiamata sincrona è ancora necessaria per rimuovere gli artefatti dello zoom.