14

Im creating this app, and it needs to get the users location - its all working properly, the thing is, that the time from accepting the use of location services, to getting the actual location takes like 5 seconds - is this normal? I've used other apps, where it goes much faster..

Here's what my code looks like:

override func viewDidLoad() {
    super.viewDidLoad()

    // Ask for Location-Authorisation from the User.
    self.locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.requestLocation()
    }

    mapView.delegate = self

}



func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let locValue: CLLocationCoordinate2D = manager.location!.coordinate

    let initialLocation = CLLocation(latitude: locValue.latitude, longitude: locValue.longitude)

    self.centerMapOnLocation(initialLocation)
}

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    print("could not get location")
}

But the time from the application gets the location to put into the centerMapOnLocation-function, seems just to be quite long. What is to be expected, when getting a users location? I'm testing on a wifi connection, so I know its not because the internet is slow, or its a bad connection...

Anyone have an idea? :)

Best regards!

Nicolai Harbo
  • 1,064
  • 12
  • 25
  • 2
    try setting the accuracy and use locationManager.startUpdatingLocation(). I do that, and get answer within a second (on the device). – Jens Peter Feb 15 '17 at 09:46
  • Awesome! locationManager.startUpdatingLocation() did the trick! I swapped it with .requestLocation(), and now its working like a charm! Thanks @JensPeter - would like to give you the correct answer, but I cant as its a comment :/ write an answer, and i'll accept it :) – Nicolai Harbo Feb 15 '17 at 10:19

4 Answers4

19

Try setting the accuracy and use locationManager.startUpdatingLocation(). I do that, and get answer within a second (on the device).

Jens Peter
  • 715
  • 6
  • 10
  • But the purpose of requestLocation is to get the location just once. Else it keeps on. giving the location until its stopped, the result it that it drains the battery – Satyam Jan 10 '22 at 12:06
8

From the documentation of requestLocation():

This method returns immediately. Calling it causes the location manager to obtain a location fix (which may take several seconds) and call the delegate’s locationManager(_:didUpdateLocations:) method with the result.

Source

So basically, everything is fine with your code, it's just how the framework is built.

user3581248
  • 964
  • 10
  • 22
  • 8
    In my experience, requestLocation() is considerably slower (2x-3x) to return a result compared to startUpdatingLocation() – nikkumang Jan 09 '18 at 10:33
  • 3
    Yes, in my experience, requestLocation() is also much slower than startUpdatingLocation(). I'm not sure why, but I think it has something to do with location accuracy. Maybe requestLocation is trying to be super accurate every time, while startUpdatingLocation is less accurate? I'm not sure... – Daniel Jones Apr 28 '18 at 23:56
  • 3
    requestLocation() is slow because it starts location services, finds location and when it finds it the location services are stoped. If you use startUpdatingLocation() your location is updated frequently (every N seconds) and also drains more battery because of this. So consider how you are using it. If you use startUpdatingLocation() then maybe stop it with stopUpdatingLocation() after you receive location... – GrandFelix Sep 28 '18 at 04:51
3

When initializing your location manager, add startUpdatingLocation():

let manager = CLLocationManager()
 manager.delegate = self
 manager.requestWhenInUseAuthorization()
 manager.requestLocation()
 manager.startUpdatingLocation()

Without startUpdatingLocation() geo-location takes about 5 seconds, with it, the request executes nearly immediately.

LineDrop
  • 461
  • 4
  • 5
1

If you don't want to delay the app's launch for the location manager, consider deploying two location managers (in the app delegate), tasking one with generating a location quickly and the other with generating a location accurately:

fastLoc.delegate = self
fastLoc.desiredAccuracy = kCLLocationAccuracyThreeKilometers
fastLoc.requestWhenInUseAuthorization()
fastLoc.startUpdatingLocation()

bestLoc.delegate = self
bestLoc.desiredAccuracy = kCLLocationAccuracyBest
bestLoc.requestWhenInUseAuthorization()
bestLoc.requestLocation()

The combination of 3 km accuracy with startUpdatingLocation() should return a location almost instantly, almost always before the root view controller is even ready to go. bestLoc manager is likely to return a location well after the user has launched the app but it will be very accurate.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    switch manager {
    case fastLoc:
        fastLoc.stopUpdatingLocation()
        deviceLocation = locations.last! // set property with fast loc
        
    case bestLoc:
        deviceLocation = locations.last! // overwrite property with best loc
    default:
        break
    }
}
trndjc
  • 11,654
  • 3
  • 38
  • 51