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?

Was it helpful?

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.

enter image description here

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]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top