4
votes

I'm making an app with a MapView and I want to persist the position of the map with NSUserDefaults. Whenever the map's position changes I save the map region. When the view loads, if there is a saved map region then I call setRegion on the MapView with the saved region. The issue is that the map position after loading is not the same as the position that was last saved. Here is the code:

override func viewDidLoad() {
    super.viewDidLoad()

    // Read saved coordinate region from NSUserDefaults
    if let array = self.readSavedMapPosition() {
        print("Loading saved region")
        let mkcr = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: array[0], longitude: array[1]), span: MKCoordinateSpan(latitudeDelta: array[2], longitudeDelta: array[3]))
            self.mapView.setRegion(mkcr, animated: true)
    }
}

func saveMapPosition(mkcr: MKCoordinateRegion) {
    let defaults = NSUserDefaults.standardUserDefaults()
    let array = [mkcr.center.latitude, mkcr.center.longitude, mkcr.span.latitudeDelta, mkcr.span.longitudeDelta]
    print("map position saved: \(array)")
    defaults.setObject(array, forKey: savedMKCRArray)
}

func readSavedMapPosition() -> [Double]? {
    let defaults = NSUserDefaults.standardUserDefaults()
    let array = defaults.objectForKey(savedMKCRArray) as? [Double]
    print("map position read: \(array)")
    return array
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    print("Map view region changed, saving new position")
    let currentRegion = mapView.region
    self.saveMapPosition(currentRegion)
}

When running the app in the simulator, I'll get output like this in the console:

map position read: Optional([42.6751429892564, -79.4232294187297, 2.8355733828259, 3.85688659929976])

Loading saved region

Map view region changed, saving new position

map position saved: [39.9600790604276, -79.4232294187296, 7.57379831196707, 9.88327223217576]

After setRegion is called, the coordinates and the span of the region are changed. Apple's documentation for setRegion explains that the map may change the region to fit the visible area of the map:

When setting a new region, the map may adjust the value in the region parameter so that it fits the visible area of the map precisely. This adjustment is normal and is done to ensure that the value in the region property always reflects the visible portion of the map. However, it does mean that if you get the value of that property right after calling this method, the returned value may not match the value you set. (You can use the regionThatFits: method to determine the region that will actually be set by the map.)

Shouldn't the region parameter to setRegion already fit the visible area of the map, since this region came from a previously saved position of the map? How can I get more reliable behavior from setRegion?

1

1 Answers

0
votes

I solved this Problem, that I don't save the last region on region change, instead of that I save the region if the view should disappear Action is triggered. Like Close button or Done button