'didUpdateLocations never called
I'm trying to get the user's location. To do so I have set the following property in the info.plist :
I have also added the following code in my viewDidLoad method as well as the function below. The problem is that the locationManager(manager, didUpdate....)
function never gets called, I also never get prompted for permission to access location, even though I have removed and installed the app again. I am testing this on my iPad, not on the simulator. The didFailWithError function never gets called either.
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("UPDATING")
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
let latitude = locValue.latitude
let longitude = locValue.longitude
latitudeText = "\(latitude)"
longitudeText = "\(longitude)"
if let a = latitudeText, b = longitudeText {
print(a)
print(b)
self.locationManager.stopUpdatingLocation()
if (userAlreadyExist()) {
dispatch_async(dispatch_get_main_queue(), {
//self.performSegueWithIdentifier("segueWhenLoggedIn", sender: self)
self.performSegueWithIdentifier("showCamera", sender: self)
// self.performSegueWithIdentifier("showTabBarController", sender: self)
})
}
else {
dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier("segueWhenLoggedOut", sender: self)
})
}
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print(error.localizedDescription)
}
EDIT :
I have added the following snippet of code :
if CLLocationManager.locationServicesEnabled() {
print("yes")
}
else {
print("no")
}
it returns yes. I have also checked on my device, locationServices are enabled, the app is listed there, however all the other apps have "While Using", "Never" or "Always" written next to them, mine doesn't have anything written.
Solution 1:[1]
where do you start the location update ? for example:
//location manager
lazy var locationManager: CLLocationManager = {
var _locationManager = CLLocationManager()
_locationManager.delegate = self
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
_locationManager.activityType = . automotiveNavigation
_locationManager.distanceFilter = 10.0 // Movement threshold for new events
_locationManager.allowsBackgroundLocationUpdates = true // allow in background
return _locationManager
}()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation() // start location manager
}
here is a working conroller code: also important to to set up Custom iOS Target Properties.
Add these two lines to the Info.plist:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
//
// ViewController.swift
// LocationTest2
import UIKit
import CoreLocation
class ViewController: UIViewController {
//location manager
lazy var locationManager: CLLocationManager = {
var _locationManager = CLLocationManager()
_locationManager.delegate = self
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
_locationManager.activityType = . automotiveNavigation
_locationManager.distanceFilter = 10.0 // Movement threshold for new events
// _locationManager.allowsBackgroundLocationUpdates = true // allow in background
return _locationManager
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//allow location use
locationManager.requestAlwaysAuthorization()
print("did load")
print(locationManager)
//get current user location for startup
// if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
// }
}
}
// MARK: - CLLocationManagerDelegate
extension ViewController: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
print("**********************")
print("Long \(location.coordinate.longitude)")
print("Lati \(location.coordinate.latitude)")
print("Alt \(location.altitude)")
print("Sped \(location.speed)")
print("Accu \(location.horizontalAccuracy)")
print("**********************")
}
}
}
Solution 2:[2]
for me worked:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locationManager update")
}
instead of this
private func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locationManager update")
}
Solution 3:[3]
Also make sure you have set the custom location to simulator as by default it will be None ... In the simulator go to Debug -> Location-> .
It should also be noted that locationManager:didFailWithError: will run if the location is not set in the simulator, as you'd expect.
Solution 4:[4]
A very subtle cause for this bug in Swift code. Don't define the delegate call didUpdateLocations as private or fileprivate. The location manager won't be able to find or call it if you do.
Good:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
Bad:
fileprivate func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
Solution 5:[5]
I looked for answers high and low. This is the only thing that worked for me: Change the func for didUpdateToLocation to:
func locationManager(_: CLLocationManager, didUpdateToLocation newLocation: CLLocation!,fromLocation oldLocation: CLLocation!) {
}
Note the subtle change of "as _: CLLocationManager", instead of "manager: CLLocationManager".
Solution 6:[6]
You should call startUpdatingLocation()
inside the didDetermineState
delegate method
if CLLocationManager.authorizationStatus() != .authorizedWhenInUse {
locationManager.requestWhenInUseAuthorization()
}else{
locationManager.startUpdatingLocation()
}
//later
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse:
manager.startUpdatingLocation()
break
case .authorizedAlways:
manager.startUpdatingLocation()
break
case .denied:
//handle denied
break
case .notDetermined:
manager.requestWhenInUseAuthorization()
break
default:
break
}
}
Solution 7:[7]
I was using AppDelegate as CLLocationManagerDelegate instead of ViewController like in most examples, this was the code I had
// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var locationManager: CLLocationManager?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
return true
}
}
and I was trying to get updates when exit event was called
// AppDelegate.swift
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
if !CLLocationManager.locationServicesEnabled() {
return
}
let locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
return
}
}
But this didn't work. Instead I had to move the configuration of locationManager to AppDelegate class, and only start the updates in AppDelegate extension.
Like this
// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var locationManager: CLLocationManager?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
/* This was the catch, it needs to be here instead of inside extension */
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager?.distanceFilter = kCLDistanceFilterNone
self.locationManager?.allowsBackgroundLocationUpdates = true
/* */
return true
}
}
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
if !CLLocationManager.locationServicesEnabled() {
return
}
/* Only do this here */
manager.startUpdatingLocation()
return
}
}
Then it started working, and sending continuous location updates. Also I tested on simulator.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | user924 |
Solution 3 | Keshav |
Solution 4 | SafeFastExpressive |
Solution 5 | Uma Madhavi |
Solution 6 | Krunal Nagvadia |
Solution 7 | JJ. |