iosswiftmapboxuserlocation

Why userLocation returns (-180.0,-180.0) coordinates on Mapbox?


I use Mapbox with Swift 4 and I have a problem when I want to display the user location. I don't understand why the user location is not set as it should be.

I would get the user location coordinates in the viewDidLoad() method. To do so, I have set MGLMapViewDelegate and CLLocationManagerDelegate in my ViewController declaration. Then, in my viewDidLoad() I have:

// Mapview configuration
let mapView = MGLMapView(frame: self.mapView.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.showsUserLocation = true
mapView.setUserTrackingMode(.follow, animated: true)
mapView.delegate = self

self.mapView.addSubview(mapView)

// User location        
print("User location:")
print(mapView.userLocation!.coordinate)

But I get this:

CLLocationCoordinate2D(latitude: -180.0, longitude: -180.0)

I think it is because the location is not set when the view loads, but I need to get values in viewDidLoad().

What should I do, and why the line mapView.userLocation!.coordinate doesn't work?


EDIT

In fact, I want to use MapboxDirections to display on the map a line between the user location and a fixed point. To do it, I use this code (see the first comment):

let waypoints = [
    // HERE I would use the user location coordinates for my first Waypoint
    Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox"),
    Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House"),
        ]
let options = RouteOptions(waypoints: waypoints, profileIdentifier: .automobileAvoidingTraffic)
options.includesSteps = true

_ = directions.calculate(options) { (waypoints, routes, error) in
    guard error == nil else {
        print("Error calculating directions: \(error!)")
        return
    }

    if let route = routes?.first, let leg = route.legs.first {
        print("Route via \(leg):")

        let distanceFormatter = LengthFormatter()
        let formattedDistance = distanceFormatter.string(fromMeters: route.distance)

        let travelTimeFormatter = DateComponentsFormatter()
        travelTimeFormatter.unitsStyle = .short
        let formattedTravelTime = travelTimeFormatter.string(from: route.expectedTravelTime)

        print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)")

        if route.coordinateCount > 0 {
            // Convert the route’s coordinates into a polyline.
            var routeCoordinates = route.coordinates!
            let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: route.coordinateCount)

            // Add the polyline to the map and fit the viewport to the polyline.
            mapView.addAnnotation(routeLine)
            mapView.setVisibleCoordinates(&routeCoordinates, count: route.coordinateCount, edgePadding: .zero, animated: true)
        }
    }
}

Solution

  • Larme is correct: the user's location typically isn't available yet in -viewDidLoad. Use the -mapView:didUpdateUserLocation: delegate method to be notified when the user's location becomes available and when it updates.

    If you need the user’s location before a map is shown, consider running your own CLLocationManager.

    -180, -180 is the kCLLocationCoordinate2DInvalid constant from Core Location. You should typically check if CLLocationCoordinate2DIsValid() before trying to display CLLocationCoordinate2D on a map.