发布版本中 rawValue 的重新声明无效

Invalid redeclaration of rawValue in Release build

我有一个混合项目,遇到了一个有趣的问题。 有一个枚举,定义在 obj-c

typedef NS_ENUM (NSUInteger, ABCCategory) {
  ABCCategoryFirst,
  ABCCategorySecond
};

接下来,有一个 swift 文件,其中定义了扩展名

extension ABCCategory: RawRepresentable {

  public typealias RawValue = String

  public init(rawValue: RawValue) {
    switch rawValue {
    case "first":
      self = .first
    case "second":
      self = .second
    default:
      self = .first
    }
  }

  public var rawValue: RawValue {
    get {
      switch self {
      case .first:
        return "first"
      case .second:
        return "second"
      }
    }
  }
}

在 Debug 配置中一切正常,但是当我切换到 Release 时它没有构建,说:Invalid redeclaration of 'rawValue' 我试过删除 typealias,用 String 替换 RawValue(因此协议可以隐式猜测值),使构造函数像协议中那样可选(并且隐式解包可选) - 不行。

我明白用字符串扩展 Int 枚举有点奇怪,但为什么它在 Release 中停止构建而在 Debug 中工作绝对完美?

是否有一些不同的机制来处理 enums/classes/extensions 的发布配置?

The raw value syntax for enums in Swift is “just” a shorthand for conformance to the RawRepresentable protocol. It’s easy to add this manually if you want to use otherwise unsupported types as raw values. Source

我不确定为什么它在调试中有效,因为当您创建类型化枚举时,您已经 'conforming' 到 RawRepresentable。因此,当您创建 NS_ENUM 时,它会像这样导入到 swift 中:

public enum ABCCategory : UInt {
    case first
    case second
}

表示已经符合RawRepresentable。修复可以通过两种方式实现,一种是 Swift 和 Objective-C


在Swift中,我们只是删除RawRepresentable并将rawValue更改为stringValue,将RawValue更改为String:

extension ABCCategory {

    var stringValue: String {
        switch self {
        case .first: return "first"
        case .second: return "second"
        }
    }

    init(_ value: String) {
        switch value {
        case "first":
            self = .first
        case "second":
            self = .second
        default:
            self = .first
        }
    }

}

或者您可以将 Objective-C 更改为使用 NS_TYPED_ENUM。一些信息 here。但是,这会将您的枚举更改为 struct

.h

typedef NSString *ABCCategory NS_TYPED_ENUM;

extern ABCCategory const ABCCategoryFirst;
extern ABCCategory const ABCCategorySecond;

.m

ABCCategory const ABCCategoryFirst = @"first";
ABCCategory const ABCCategorySecond = @"second";

这将由 swift 像这样导入:

public struct ABCCategory : Hashable, Equatable, RawRepresentable {

     public init(rawValue: String)
}

public static let first: ABCCategory
public static let second: ABCCategory