20

I'm using CoreLocation to successfully determine the user's location. However when i try to use the CLLocationManagerDelegate method:

func locationManager(_ manager: CLLocationManager!, didFailWithError error: NSError!)

I run into problems with the error term.

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
    println("didFailWithError \(error)")

    if let err = error {
        if err.code == kCLErrorLocationUnknown {
            return
        }
    }
}

This results in a 'Use of unresolved identifier kCLErrorLocationUnknown' error message. I know that the kCLErrors are enums and that they have evolved in Swift but I'm stuck.

Magnas
  • 3,507
  • 4
  • 27
  • 40

3 Answers3

42

Update for Swift 4: The error is now passed to the callback as error: Error which can be cast to an CLError:

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    if let clErr = error as? CLError {
        switch clErr {
        case CLError.locationUnknown:
            print("location unknown")
        case CLError.denied:
            print("denied")
        default:
            print("other Core Location error")
        }
    } else {
        print("other error:", error.localizedDescription)
    }
}

Older answer: The Core Location error codes are defined as

enum CLError : Int {
    case LocationUnknown // location is currently unknown, but CL will keep trying
    case Denied // Access to location or ranging has been denied by the user
    // ...
}

and to compare the enumeration value with the integer err.code, toRaw() can be used:

if err.code == CLError.LocationUnknown.toRaw() { ...

Alternatively, you can create a CLError from the error code and check that for the possible values:

if let clErr = CLError.fromRaw(err.code) {
    switch clErr {
    case .LocationUnknown:
        println("location unknown")
    case .Denied:
        println("denied")
    default:
        println("unknown Core Location error")
    }
} else {
    println("other error")
}

UPDATE: In Xcode 6.1 beta 2, the fromRaw() and toRaw() methods have been replaced by an init?(rawValue:) initializer and a rawValue property, respectively:

if err.code == CLError.LocationUnknown.rawValue { ... }

if let clErr = CLError(rawValue: code) { ... }
Martin R
  • 488,667
  • 78
  • 1,132
  • 1,248
7

In Swift 3 it's now:

if error._code == CLError.denied.rawValue { ... }
chriskryn
  • 121
  • 1
  • 4
  • This is correct. Just in case, casting to NSError will probably be deprecated soon: `let code = (error as NSError).code; if code == CLError.denied.rawValue { ... } // CODE SMELL!!` – Rob Nov 08 '16 at 16:36
3

Swift 4.1:

func locationManager(_: CLLocationManager, didFailWithError error: Error) {
    let err = CLError.Code(rawValue: (error as NSError).code)!
    switch err {
    case .locationUnknown:
        break
    default:
        print(err)
    }
}
Simon Bengtsson
  • 6,488
  • 3
  • 44
  • 79