Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I save a GMSCameraPosition?

In my map app, I want to save the camera position just before the app terminates. When the app starts again, I want the camera to move to the saved position. This way, the user can continue using the map from where he/she left off last time.

So in the VC that contains the map view, I added this:

deinit {
    let mapView = self.view as! GMSMapView
    UserDefaults.standard.set(mapView.camera.target.longitude, forKey: "lastLongitude")
    UserDefaults.standard.set(mapView.camera.target.latitude, forKey: "lastLatitude")
    UserDefaults.standard.set(mapView.camera.zoom, forKey: "lastZoom")
    UserDefaults.standard.set(mapView.camera.bearing, forKey: "lastBearing")
    UserDefaults.standard.set(mapView.camera.viewingAngle, forKey: "lastViewingAngle")
}

override func viewDidLoad() {
    let camera = GMSCameraPosition.camera(withLatitude: 0, longitude: 0, zoom: 3)
    let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    mapView.isMyLocationEnabled = true
    view = mapView

    mapView.delegate = self

    // ...

    let longitude = UserDefaults.standard.double(forKey: "lastLongitude")
    let latitude = UserDefaults.standard.double(forKey: "lastLatitude")
    let zoom = UserDefaults.standard.float(forKey: "lastZoom")
    let bearing = UserDefaults.standard.double(forKey: "lastBearing")
    let viewingAngle = UserDefaults.standard.double(forKey: "lastViewingAngle")
    mapView.animate(to: GMSCameraPosition(target: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoom: zoom, bearing: bearing, viewingAngle: viewingAngle))
}

The logic here is that when the VC is deinitialized, I save the map view's camera position to UserDefaults. Then in viewDidLoad, I move the camera to the saved position.

When I run the app, I moved the camera to an arbitrary position, pressed the stop button in Xcode, and opened up the app again. The camera is back at the initial position (0, 0) again, instead of the arbitrary position I moved it to.

After debugging, I found that deinit isn't even called! I am really confused.

Is this right way to save the camera position? What have I done wrongly?

like image 404
Sweeper Avatar asked Sep 19 '16 16:09

Sweeper


1 Answers

Declare class as Final

final class viewController: UIViewController, GMSMapViewDelegate
  • Declare mapView object as Global:

ViewController.swift

var mapView:GMSMapView!
  • Make singleton class object as follow:

ViewController.swift

static let sharedInstance: MapController = MapController()
  • Get stored from UserDefault as below:

ViewController.swift in ViewDidLoad()

let camera = GMSCameraPosition.camera(withLatitude: 0, longitude: 0, zoom: 3)
    MapController.sharedInstance.mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
 //    ...
    let tempUser: UserDefaults = UserDefaults.standard
    let longitude = tempUser.double(forKey: "lastLongitude")
    let latitude = tempUser.double(forKey: "lastLatitude")
    let zoom = tempUser.float(forKey: "lastZoom")
    let bearing = tempUser.double(forKey: "lastBearing")
    let viewingAngle = tempUser.double(forKey: "lastViewingAngle")
    MapController.sharedInstance.mapView.animate(to: GMSCameraPosition(target: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoom: zoom, bearing: bearing, viewingAngle: viewingAngle))

When save data in Userdefault then always synchronize() data after all value are set successfully.

  • Below Function save data every time when mapView camera position.

ViewController.swift

func mapView(mapView: GMSMapView, idleAtCameraPosition position: GMSCameraPosition) {
        let tempUser: UserDefaults = UserDefaults.standard
        tempUser.set(mapView.camera.target.longitude, forKey: "lastLongitude")
        tempUser.set(mapView.camera.target.latitude, forKey: "lastLatitude")
        tempUser.set(mapView.camera.zoom, forKey: "lastZoom")
        tempUser.set(mapView.camera.bearing, forKey: "lastBearing")
        tempUser.set(mapView.camera.viewingAngle, forKey: "lastViewingAngle")
        tempUser.synchronize()


}
  • If Want to store data only when app is terminated then add following code into AppDelegate.swift:

Appdelegate.swift

func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        var saveLocation = MapController.sharedInstance
        let mapView = saveLocation.mapView as GMSMapView
        let tempUser: UserDefaults = UserDefaults.standard
        tempUser.set(mapView.camera.target.longitude, forKey: "lastLongitude")
        tempUser.set(mapView.camera.target.latitude, forKey: "lastLatitude")
        tempUser.set(mapView.camera.zoom, forKey: "lastZoom")
        tempUser.set(mapView.camera.bearing, forKey: "lastBearing")
        tempUser.set(mapView.camera.viewingAngle, forKey: "lastViewingAngle")
        tempUser.synchronize()

    }
like image 127
Sakir Sherasiya Avatar answered Oct 21 '22 11:10

Sakir Sherasiya