2009-09-05 33 views
15

Estoy ahorrando región del mapa en valores predeterminados del usuario cuando mi aplicación para el iPhone se está cerrando de esta manera:MKMapView Mostrar Guardados incorrectamente región

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"]; 

Cuando lanza aplicación de nuevo, Ш leer los valores de nuevo de la misma manera, por lo que la usuario puede ver exactamente lo mismo ver mapa ya que fue la última vez:

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 región que he leído de usuario por defecto es (como es lógico) es exactamente la misma que cuando se guardó. Tenga en cuenta que lo que se guarda proviene directamente del mapa, por lo que no se transforma de ninguna manera. Lo configuro nuevamente en el mapa con el método setRegion:, ¡pero luego es diferente!

resultados Ejemplo:

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

¿Alguien sabe por qué sucede esto?

+0

Encontré una solución para obtener exactamente la región del mapa que desea: Ver mi publicación en http://stackoverflow.com/questions/3612007/mkmapview-setregion-snaps-to-predefined-zoom-levels/7935 – AlexWien

Respuesta

2

Tuve el mismo problema. Esto es muy frustrante Parece que la documentación de MKMapView es incorrecta en algunas áreas con respecto a los tipos de datos.

Si establece los parámetros de región como (dobles) obtendrá el error que está teniendo. Sin embargo, si los parámetros de la región son pasados ​​(float) obtendrá el comportamiento correcto.

Así que trate

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

Gracias por Tu respuesta. He intentado resolver mi problema de esta manera, pero todavía no tengo suerte ... Estoy bastante seguro de que el problema es el truncamiento del doble para flotar, pero por ahora no tengo ni idea de cómo solucionarlo. ¿Alguien más por favor? –

0

No puedo verificar que esto funciona. ¿Alguien más puede hacerlo? Estaría dispuesto a apostar que lo que estás viendo es el efecto del truncamiento de tus dobles en flotadores. En algunos casos, cuando esto me sucede, descubro que puedo multiplicar el lapso por 0,9999 y restablecer la región, y entonces será lo que quiero. Pero no en todas las regiones, a veces es muy diferente, hasta un 20% diferente, especialmente para tramos pequeños.

+0

eh, lo siento - esto está relacionado con el siguiente comentario que comienza con: "Tuve el mismo problema. Esto es muy frustrante ..." – Colin

8

El problema aquí es cuando establece la región, el nivel de zoom del mapa "se ajusta" al umbral de zoom más cercano. (Sospecho que estos umbrales de zoom son las cantidades de zoom que se obtienen cuando toca dos veces o toca dos veces)

Por lo tanto, si el mapa muestra el nivel de zoom 1 por ejemplo, y establece la región en ese mismo lapso valor de este modo: region = [mapView region]; [mapView setRegion:region]; se "ajustará" al nivel de zoom más cercano por encima de nivel 1, es decir, nivel 2 y se alejará aproximadamente un factor de dos.

La solución para el póster original es reducir ligeramente los valores de span antes de configurar la región, de modo que cuando la vista salga, salte al nivel de zoom en el que estaba, no al anterior.

p. Ej.

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

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

Si el usuario hubiera sido el zoom con camas de grifos (y por tanto saltar de umbral en umbral) esto funciona bastante bien, devolviéndolas al mismo punto de vista casi exactamente.

Sin embargo, si pellizcan y la vista está a medio camino entre los umbrales de zoom, se ajustará al próximo nivel. No es tan bueno en ese caso, pero todavía no hay ninguna solución.

Hay errores abiertos en el radar de Apple para esto, con suerte se solucionará en una versión futura.

+0

No es un error. Está bien documentado y se comporta exactamente como está documentado.https://developer.apple.com/library/iOS/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html – Frizlab

+0

@frizlab el enlace está muerto ¿a qué apuntaba? – 3366784

+0

@ 3366784 https://developer.apple.com/documentation/mapkit/mkmapview. De todos modos, el comentario está desactualizado, ahora el 'MKMapView' funciona como se esperaba. – Frizlab

2

OK, así que he estado luchando con este problema desde hace un tiempo y creo que he encontrado una solución efectiva inspirada en la teoría de Crufty (MKMapView show incorrectly saved region). Básicamente, si configura la región de la vista del mapa con los valores que obtiene de NSUserDefaults después de que la vista del mapa haya realizado su carga inicial (completa con el comportamiento "complemento"), la región del mapa será lo que esperaría que fuera . El truco está en encontrar un gancho en el código de tu aplicación en algún lugar aguas abajo de la vista del mapa que se ha inicializado. No es bonito, pero funciona perfectamente para mí. Gracias a Crufty por la información.

0

He encontrado un mayor éxito usando un factor de multiplicación de 0.9 en vez de 0.999, pero a veces lo empuja pero parece acercarse más al zoom deseado. ¡Me encantaría resolver este problema solo para decir que lo superé! jaja

-1

Si configura el MapView en InterfaceBuilder, asegúrese de que usted no hace esto:

_mapView = [[MKMapView alloc] init]; 

Tan pronto como me quita esta línea init, mi ver mapa de repente comenzó a responder correctamente todas las actualizaciones Lo envié. Sospecho que lo que sucede es que si haces el alloc init, en realidad está creando otra vista que no se muestra en ninguna parte. El que ves en la pantalla es el que inicializaste en tu plumilla. Pero si se asigna una nueva, entonces eso es algo en otro lugar y no va a hacer nada.

0

Pruebe también para almacenar actitud como

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

y cuando u configurar su mapa

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

Esto establecerá para misma región misma cámara. En su caso, solo establece la región pero no la cámara.

0

Aquí es una extensión Swift para codificar y decodificar correctamente 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) 
    } 
} 

Esto es cómo 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

Recientemente me dio en el mismo. Usando los puntos de vista de las respuestas anteriores, los siguientes 4 aplicación rápida funciona para mí:

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

Esto establece una zona inicial del zoom cuando el controlador de vista de mapa es empujado a la vista. La llamada síncrona a setInitialRegion establecerá una región ajustada a un nivel de zoom. La llamada asincrónica a setInitialRegion establecerá la región exacta. La llamada síncrona sigue siendo necesaria para eliminar artefactos de zoom.

Cuestiones relacionadas