【问题标题】:Check NSError code in swift快速检查 NSError 代码
【发布时间】:2014-08-11 08:05:17
【问题描述】:

我正在尝试检查 Swift 中的错误代码值,发现自己对新的结构类型和转换有点困惑。

我想要做的只是获取一个在处理程序闭包中传递的 NSError 对象,并通过将其与存储在 CMError 结构中的值进行比较来检查其代码类型。在 Objective-C 中我会简单地写

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

在 Swift 中,当我编写我期望的等价物时

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

我收到错误找不到接受所提供参数的 '!=' 的重载。这指向类型转换错误。实际上CMErrorMotionActivityNotAuthorizedCMError 类型,它是一个Swift 结构。而且我似乎无法在CMError 类型和Int 类型之间转换,即error.code

那么如何检查我的错误代码?


注 1

如果我尝试分解并显式转换:

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

我收到荒谬的错误消息无法将表达式的类型“Int”转换为类型“Int”


注2

文档说CMError 被定义为

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

在斯威夫特。在 Objective-C 中它被定义为

typedef enum {
   CMErrorNULL = 100,
   CMErrorDeviceRequiresMovement,
   CMErrorTrueNorthNotAvailable,
   CMErrorUnknown,
   CMErrorMotionActivityNotAvailable,
   CMErrorMotionActivityNotAuthorized,
   CMErrorMotionActivityNotEntitled,
   CMErrorInvalidParameter
} CMError;

【问题讨论】:

  • 既然是 ObjC 中的enum,你试过CMError.MotionActivityNotAuthorized吗?
  • 我试过了。它说 'CMError.Type' 没有名为 'MotionActivityNotAuthorized' 的成员
  • 在我看来,由于他们没有使用 NS_ENUM 来“现代化”他们的 ObjC 枚举,因此 objc->swift 翻译器没有正确翻译枚举并以 struct 结束...可能值得报告错误,除非有人弄清楚原因
  • 是的,我也怀疑有错误,但我认为更可能是我错过了一些东西。如果没有人弄清楚出了什么问题,我会提交一份错误报告,提供这个问题作为参考。
  • 我查看了 iOS 8 API 差异,CMError 不在核心运动部分,似乎核心运动团队很懒惰或不知道 swift :p

标签: swift core-motion nserror


【解决方案1】:

Jack Wu 的 cmets 是对的——这看起来像一个非现代化的枚举,filing a bug about that 将是一个好主意。与此同时……

按住命令单击 Swift 文件中的 CMError 声明,您将获得类型和相关常量的 Swift 定义。 CMErrorMotionActivityNotAuthorized 和朋友不是Int 的子类型,它们是CMError 结构的实例,它包含一个整数value。该值是 CUnsignedInt,Swift 不会自动将其转换为已签名的 Int — Swift 作为“安全”语言的一部分是避免隐式类型转换可能导致上溢/下溢导致 @ 987654322@.

因此,您的查询应该如下所示:

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

(还稍微精简了代码以使用类型推断。)

【讨论】:

  • 感谢瑞克斯特!由于类型差异,我已经尝试将CUnsignedInt 转换为Int。我没有意识到需要的不是演员阵容,而是一种转变。另外,我错过了 .value 属性。
  • 是的。要记住的一件好事:as 不是像 C 中那样的“强制转换”,而是特别是“低调”。它只允许您将一般类型的值视为更具体的类型。任何其他类型转换,即使在看起来相关的类型之间,也使用初始化器语法。
【解决方案2】:

Swift 4.0 中,您可以选择 CMPedometer.authorizationStatus(),这让您的生活更轻松 :) 下面是我要做的,首先检查版本是否是iOS 11+,我们可以使用这种方法,否则我们使用错误解析方法:

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
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    相关资源
    最近更新 更多