bwc
bwc

Reputation: 1842

Google Maps Start at User Location

I am using Firebase and Google Maps within my app for user accounts and for the main map view. In my app, I want it to start at the user's location and then have them be able to move the map around, but there are a few issues.

  1. Once the user is authenticated via. Firebase, I have it try to get the users location, but it usually returns nil even when I have location services enabled for the app. Here's my code for that:

    if let mylocation = mapView.myLocation {
        print("User's location: \(mylocation)")
    } else {
        print("User's location is unknown")
    }
    

    This is in my viewDidLoad function also. I do have the code for asking permission to use location as well as the Privacy statement in my Info.plist file.

  2. If my map happens to load and the user location is found, I try to have it center the view on the user's location. However, it can't get the user's location in time, or so it seems, and the map loads at some other location and it won't update to the user's location.

So here's my question

Is there any way to load the map and have it update to the user's location without it being stuck there for the entirety of the apps use? An example of what I want is basically a Google Maps clone where it starts at the user's location and they are able to interact with the map without it trying to consistently update the map to the user's location. If not, is there a way to wait for the location to be found before loading the map? I tried using GCD (Grand Central Dispatch), but that didn't work. I feel like that isn't my best option, waiting for the location to load before displaying the map that is, because there are many issues that could happen with it. If neither of these are options, what would you do? Thanks!

Upvotes: 0

Views: 774

Answers (1)

Thomas G.
Thomas G.

Reputation: 1003

If My Location is enabled, reveals where the user location dot is being drawn. If it is disabled, or it is enabled but no location data is available, this will be nil. This property is observable using KVO.

Since the myLocation on the GMSMapView is observable with KVO to observe this value should solve your problem.

Here some example code:

Add self as an observer for the myLocation property of your GMSMapView instance.

self.mapview.addObserver(self, forKeyPath: "myLocation", options: NSKeyValueObservingOptions.new, context: nil)

Here you handle the changes:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        guard let update = change, let myLocation = update[NSKeyValueChangeKey.newKey] as? CLLocation else {
           return
        }
        self.mapView.camera = GMSCameraPosition.camera(withTarget: myLocation.coordinate, zoom: self.defaultTrackingZoom)
 }

Don´t forget to remove your observer somewhere e.g. deinit or viewWillDisappear

deinit 
{
   self.mapView.removeObserver(self, forKeyPath: "myLocation")  
}

In this example the map position is getting updated every time the user position has changed. If you need that position only once at start you could add a flag like myLocationFound and check that in the observeValue:forKeyPath

Hope that helps.

Upvotes: 2

Related Questions