【问题标题】:NSErrorDomain + NS_ERROR_ENUM makes type lookup ambiguous. Why?NSErrorDomain + NS_ERROR_ENUM 使类型查找模棱两可。为什么?
【发布时间】:2019-07-19 03:22:35
【问题描述】:

我有一个在 Objective-C 中看起来像这样的错误

NSString * const JKConfigurationErrorDomain;
typedef NS_ENUM(NSInteger, JKConfigurationCode) {
    JKConfigurationCodeUnknown,
    JKConfigurationCodeSomethingBad,
    JKConfigurationCodeParsing,
};

现在,这在 Swift 中使用起来很难看。但是从 Swift 4 开始,we can use NSErrorDomain and NS_ERROR_ENUM 让导入的错误在 Swift 中变得更好:

NSErrorDomain const JKConfigurationErrorDomain;
typedef NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationCode) {
    JKConfigurationCodeUnknown,
    JKConfigurationErrorSomethingBad,
    JKConfigurationErrorParsing,
};

这意味着我现在可以在 Swift 中做这样的事情:

if let myError = error as? JKConfigurationError, myError.code = .somethingBad {
    // handle it
}

不必将error 转换为NSError,然后检查其.domain,然后查看.code,它是一个整数,等等。

到目前为止,一切都很好。但是我的库被称为JKConfiguration,并且那里已经有一个JKConfiguration 对象(库的中心部分),一旦我开始在库代码中的任何位置使用JKConfiguration,我就会收到一个错误:

'JKConfiguration' 对于此上下文中的类型查找不明确

我不明白,为什么? NSErrorDomainNS_ERROR_ENUM 做了什么导致类型查找变得模棱两可,我该如何解决?

我已经尝试过的:

  • NS_ERROR_ENUM typedef 上使用NS_SWIFT_NAME 并将其重命名为其他名称。查看生成的 Swift 标头,重命名有效,但没有解决问题
  • 更改错误域的名称(以及因此在 Swift 中生成的错误类型)。似乎根据生成的 Swift 标头工作,但问题仍然存在。这是为什么呢?

【问题讨论】:

  • 请提供完整的复制说明或发布演示的 github 项目。
  • 合理的要求。这是一个相对较大的库的一部分,将尝试独立复制它。
  • 找出问题所在,编辑问题以正确重现问题。将添加一个答案。
  • 编辑了问题以正确重现错误,现在我知道出了什么问题。在下面回答。

标签: objective-c swift


【解决方案1】:

正如我最初所想的那样,问题不在于错误域的名称。库名称也不是问题。这是错误枚举名称的问题,在上面的示例中:JKConfigurationCode。

编译器对 NS_ERROR_ENUM 的枚举案例所做的工作有两个方面:

  • 使用枚举的名称并从所有枚举案例中删除该前缀,然后再将它们导入 swift
  • 使用给定名称创建一个枚举来保存这些案例。 如果给定名称以 Code 结尾,请删除该后缀。

所以最后一部分是问题所在。这意味着NS_ERROR_ENUM(AnyDomainName, JKConfigurationCode) 在 Swift 中生成一个枚举来保存名称为 JKConfiguration(没有代码)前缀的错误代码。但是这种类型在我的示例中已经存在,这导致了歧义。

所以解决办法就是改变

NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationCode)

NS_ERROR_ENUM(JKConfigurationErrorDomain, JKConfigurationSomethingCode)

或类似的。 不过不要忘记更新枚举案例的所有前缀,因为如果前缀与枚举名称不匹配,编译器似乎不会找到它们。

为什么 NS_SWIFT_NAME 不能重命名枚举? 我能说的最好的, NS_SWIFT_NAME 导致类型被重命名,但不是这种情况。这会导致为错误代码生成一个空类型(Swift 在这种情况下选择一个结构),因为 Swift 似乎没有找到这些情况。并且枚举案例的原始容器仍然具有违规名称。

【讨论】:

  • 出色的侦探工作,感谢您解释得如此清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多