Implement CLLocationManagerDelegate methods in Swift
-
21-12-2019 - |
Question
I've been trying to get this to work for awhile now, and I've come here to ask- how do I go about with using the CLLocationManagerDelegate methods in Swift? I've put this at the top of my class:
var locationManager = CLLocationManager()
I've put the following into my viewDidLoad
method:
locationManager.delegate = self
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
And I've tried using these delegate methods with no avail:
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
locationReceived = true
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationReceived = false
}
I've also tried using @optional in front of the functions, but Xcode then throws a compiler error. Any ideas?
Solution
You need to add the NSLocationAlwaysUsageDescription
or NSLocationWhenInUseUsageDescription
key to your plist if you haven't already, they are now mandatory,
iOS8+ requires one of these two strings to be set to use locations. Which one you use depends on how you intend ask for the location.
Use
NSLocationAlwaysUsageDescription
for apps that want to use the device's location even when the app is not open and being used.Use
NSLocationWhenInUseUsageDescription
for apps that want to use the device's location only when the app is open and in use.
Note: When you add the strings, before you build and run, delete the app off your device and let it do a fresh install. It seems that if the app was authorized to use locations before you upgraded to iOS8 it doesn’t ask for your permission again and doesn’t see that you set those strings. Doing a delete and clean install solves this.
Setting either of the strings prompts a pop up on install/first use along the lines of: "Allow "ThisApp" to access your location even when you are not using the App"
Here's a Screenshot of the plist file.
OTHER TIPS
First add this two line in plist file
1) NSLocationWhenInUseUsageDescription
2) NSLocationAlwaysUsageDescription
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
}
func initLocationManager() {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.locationServicesEnabled
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if (error) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
if (locationFixAchieved == false) {
locationFixAchieved = true
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var coord = locationObj.coordinate
println(coord.latitude)
println(coord.longitude)
}
}
func locationManager(manager: CLLocationManager!,
didChangeAuthorizationStatus status: CLAuthorizationStatus) {
var shouldIAllow = false
switch status {
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true) {
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
To get User Current Location :-
Step 1: let locationManager = CLLocationManager() // make object of CLLocationManager class.
Step 2: In viewDidLoad instantiate the CLLocationManager class like,
// For use in background
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if (CLLocationManager.locationServicesEnabled())
{
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
Step 3: Now implement the delegate methods of CLLocationManager
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locValue:CLLocationCoordinate2D = manager.location.coordinate
println("locations = \(locValue.latitude) \(locValue.longitude)")
}
Step 4:
Don't forget to add NSLocationAlwaysUsageDescription
in the Info.plist as in iOS 8 it is mandatory to add this. This will ask permission to use user's location.
I had the same issue. didUpdateLocations - was not working. Run your app. Go to the Settings page -> Privacy -> Location and turn off Location Services. didFailWithError will catch the error about absent Location Services. Then turn it on. Since that moment didUpdateLocations will catch locations.
This is a bit of an old thread, yet none of the above worked for me on Swift 2.2 xCode 7.3.1.
The problem is I was using:
func locationManager(manager: CLLocationManager!, didUpdateLocation locations: [AnyObject]!) {
print("Got location")
locationManager.stopUpdatingLocation()
}
And this never got called. When I changed to:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Got location")
locationManager.stopUpdatingLocation()
}
It all worked out. Seems like the delegate is not called when using [AnyObject]