使用NS_ENUM的rawValue初始化程序定义的枚举不会失败

时间:2016-03-02 21:16:42

标签: objective-c swift enums

我有一个Objective-C文件,其枚举定义如下:

typedef NS_ENUM(NSInteger, State) {
  State_ACTIVE = 0,
  State_PENDING = 1,
  State_CANCELED = 2
};

在我的swift代码中,如果我执行let state = State(rawValue: 100),通常会返回nil,因为它是一个可用的初始化程序。但是,当枚举声明为(使用NS_ENUM)时,初始化成功,并且没有迹象表明这是一个无效的枚举值。这是Xcode中的错误,还是按预期工作?

2 个答案:

答案 0 :(得分:1)

这是预期的行为。对于桥接到Swift的任何NS_ENUM,构造函数永远不会返回nil

尝试使用iOS SDK中的其他枚举来与Swift桥接,并带有意外值。它们都会返回非零值,即使是枚举未定义的rawValue

UITableViewCellStyle(rawValue: 7) // "Optional(__C.UITableViewCellStyle)"
UITableViewCellAccessoryType(rawValue: 9999) // "Optional(__C.UITableViewCellAccessoryType)"

或,unsafeBitCast

unsafeBitCast(42, UITableViewCellEditingStyle.self) // "Optional(__C.UITableViewCellStyle)"

Martin R指出,这是记录在案的 Xcode 6.3 release notes

  

导入带有未记录值的NS_ENUM类型,例如   UIViewAnimationCurve,现在可以从原始整数转换   使用init(rawValue:)初始化程序而不重置的值   nil。使用unsafeBitCast作为此问题的解决方法的代码可以   写入使用原始值初始化程序。例如:

let animationCurve =  
     unsafeBitCast(userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue,
     UIViewAnimationCurve.self)
     

现在可以改为:

let animationCurve = UIViewAnimationCurve(rawValue:  
    userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue)!

答案 1 :(得分:0)

可以在此枚举的扩展中定义一个额外的初始化程序,并实现适合您需求的行为。

extension State
{
    static var allRawCases: [Int]
    {
        var array = [Int]()
        switch State.ACTIVE
        {
        case .ACTIVE:
           array.append(State.ACTIVE.rawValue)
           fallthrough
        case .CANCELED:
           array.append(State.CANCELED.rawValue)
           fallthrough
        case .PENDING:
           array.append(State.PENDING.rawValue)
        }
        return array
    }
}

extension State
{
    init?(raw: Int)
    {
       guard State.allRawCases.contains(raw) else
       {
          return nil
       }
       self = State(rawValue: raw)!
    }
}

优点:

  1. 如果在Objective-C代码中添加/删除枚举大小写,则编译器将显示错误并采用该代码。
  2. 新构造函数的行为类似于本机swift枚举的默认构造函数(无关联值)。
  3. 在下一段代码中,最好在变量中使用nil而不是 “无效值。此值导致Swift 3 + Xcode 10崩溃 项目。

    // intValue differs from raw enumeration values e.g 100 
    guard let state = State(rawValue: intValue) else
    {
        return
    }
    
    switch state
    {
    case .ACTIVE:
        // do active staff            
    case .CANCELED:
        // do canceled staff
    case .PENDING:
        // do pending staff
    }
    

缺点:

  1. allRawCases属性与Objective-C枚举中的元素数量成比例增长。
  2. 调试大型枚举几乎不会令您满意。