Check NSError code in swift

I am trying to check the meaning of an error code in Swift and get a little confused with new types and conversions.

What I want to do is just take the NSError object passed in the handler closure and check its code type by comparing it with the value stored in the CMError structure. In Objective-C, I will just write

[pedometer queryPedometerDataFromDate:now toDate:now withHandler:^(CMPedometerData *pedometerData, NSError *error) { BOOL isAuthorized = (error.code != CMErrorMotionActivityNotAuthorized); }]; 

In Swift, when I write what I expect to be equivalent

 pedometer.queryPedometerDataFromDate(now, toDate: now) {(data:CMPedometerData!, error:NSError!) in let isAuthorised:Bool = (error.code != CMErrorMotionActivityNotAuthorized) } 

I get the error Could not find overload for '! = ', which accepts the provided arguments. This indicates a cast error. And indeed CMErrorMotionActivityNotAuthorized is of type CMError , which is a Swift string. And I cannot convert between this type of CMError and the type of Int , which is of type error.code .

So how can I check my error code?


Note 1

If I try to decompose and explicitly execute:

 let errorCode:Int = (CMErrorMotionActivityNotAuthorized as Int) let isAuthorized:Bool = (error.code != errorCode) 

I get an absurd error message. Cannot convert expression type "Int" to type "Int".


Note 2

Documentation says CMError is defined as

 struct CMError { init(_ value: CUnsignedInt) var value: CUnsignedInt } 

in Swift. In Objective-C, it is defined as

 typedef enum { CMErrorNULL = 100, CMErrorDeviceRequiresMovement, CMErrorTrueNorthNotAvailable, CMErrorUnknown, CMErrorMotionActivityNotAvailable, CMErrorMotionActivityNotAuthorized, CMErrorMotionActivityNotEntitled, CMErrorInvalidParameter } CMError; 
+6
source share
2 answers

Jack Wu's comments are right - it looks like an unmoderated listing, and throwing an error about it would be a great idea. Meanwhile...

Command-click a CMError in the Swift file, and you get a Swift definition of both type and related constants. CMErrorMotionActivityNotAuthorized and friends are not a subtype of Int , they are instances of a CMError structure that contains an integer value . This value is CUnsignedInt , and Swift does not automatically convert it to a signed Int for you - the Swift part, which is a "safe" language, avoids situations where implicit type conversions can lead to overrun / inadmissibility that cause errors .

So your query should look something like this:

 pedometer.queryPedometerDataFromDate(now, toDate: now) { data, error in let isAuthorized = (error.code != Int(CMErrorMotionActivityNotAuthorized.value)) } 

(Also shortened the code a bit to use type inference.)

+7
source

in Swift 4.0 you have the option CMPedometer.authorizationStatus() , which makes your life a little easier :) Here is what I would do, first check the version, if it is iOS 11 + , we can use this method, otherwise we will use the error analysis method :

 CMPedometer().queryPedometerData(from: Date(), to: Date()) { (_, error) in let isAuthorised: Bool = { if #available(iOS 11.0, *) { return CMPedometer.authorizationStatus() == .authorized } else { if let error = error as NSError? { return error.code != Int(CMErrorMotionActivityNotAuthorized.rawValue) } else { return true } } }() if isAuthorised { // do your stuff } } 
0
source

Source: https://habr.com/ru/post/971102/


All Articles