【问题标题】:Swift remove .rawValue from enumsSwift 从枚举中删除 .rawValue
【发布时间】:2018-02-22 18:34:26
【问题描述】:

我有这个枚举:

enum DMED: String {
    case money = "DMMoney"
    case netWorth = "DMNetWorth"
    case businessNum = "DMBusinessNum"
    case generalEPM = "DMGeneralEPM"
    case generalThreat = "DMGeneralThreat"
}

在我的课程中,我有这个解码器功能:

required init?(coder aDecoder: NSCoder) {
    self.money = (aDecoder.decodeDouble(forKey: DMED.money.rawValue))
    self.netWorth = (aDecoder.decodeDouble(forKey: DMED.netWorth.rawValue))
    self.businessNum = (aDecoder.decodeInteger(forKey: DMED.businessNum.rawValue))
    self.generalEPM = (aDecoder.decodeInteger(forKey: DMED.generalEPM.rawValue))
    self.generalThreat = (aDecoder.decodeInteger(forKey: DMED.generalThreat.rawValue))
}

我很想知道是否可以从所有枚举调用中删除 .rawValue。感谢您的帮助。

【问题讨论】:

  • 因为你需要一个字符串键来解码你必须使用rawValue的值,就像你现在一样。当然,您可以将变量添加到枚举中,例如 var key: String,但您仍然必须使用 DMED.money.key

标签: swift enums


【解决方案1】:

如果您仅使用 enum 值以便它们可以用作 String 常量,则应更改代码以使用带有 static 值的 struct

struct DMED {
    static let money = "DMMoney"
    static let netWorth = "DMNetWorth"
    static let businessNum = "DMBusinessNum"
    static let generalEPM = "DMGeneralEPM"
    static let generalThreat = "DMGeneralThreat"
}

required init?(coder aDecoder: NSCoder) {
    self.money = (aDecoder.decodeDouble(forKey: DMED.money))
    self.netWorth = (aDecoder.decodeDouble(forKey: DMED.netWorth))
    self.businessNum = (aDecoder.decodeInteger(forKey: DMED.businessNum))
    self.generalEPM = (aDecoder.decodeInteger(forKey: DMED.generalEPM))
    self.generalThreat = (aDecoder.decodeInteger(forKey: DMED.generalThreat))
}

【讨论】:

  • 有没有办法做到:(forKey: .money) 而不是(forKey: DMED.money)
  • @RiccardoPerego No. .money 是模棱两可的,没有说明它来自哪里。枚举也没有办法。
  • 这种静态属性方法也可以与没有案例的枚举一起使用
  • @LeoDabus 真的。将 struct 更改为 enum。我不知道这两种方法有什么好处。
  • @rmaddy 一个枚举没有初始化器
【解决方案2】:

您可以在NSCoder 上添加一个扩展来处理DMED 键:

extension NSCoder {

    func decodeDouble(forKey key: DMED) -> Double  {
        return decodeDouble(forKey: key.rawValue)
    }

    func decodeInteger(forKey key: DMED) -> Int {
        return decodeInteger(forKey: key.rawValue)
    }
}

self.money = aDecoder.decodeDouble(forKey: .money)

或者,如果您想让方法更通用,并使用任何字符串枚举,您可以使方法覆盖通用:

extension NSCoder {

    func decodeDouble<R: RawRepresentable>(forKey key: R) -> Double where R.RawValue == String {
        return decodeDouble(forKey: key.rawValue)
    }

    func decodeInteger<R: RawRepresentable>(forKey key: R) -> Int where R.RawValue == String {
        return decodeInteger(forKey: key.rawValue)
    }
}

self.money = aDecoder.decodeDouble(forKey: DMED.money)

或者,利用类型推断支持,您可以声明一个更通用的方法:

extension NSCoder {

    func decode<R: RawRepresentable>(forKey key: R) -> Double where R.RawValue == String {
        return decodeDouble(forKey: key.rawValue)
    }

    func decode<R: RawRepresentable>(forKey key: R) -> Int where R.RawValue == String {
        return decodeInteger(forKey: key.rawValue)
    }

    func decode<R: RawRepresentable>(forKey key: R) -> Any? where R.RawValue == String {
        return decodeObject(forKey: key.rawValue)
    }
}

required init?(coder aDecoder: NSCoder) {
    self.money = aDecoder.decode(forKey: DMED.money)
    self.netWorth = aDecoder.decode(forKey: DMED.netWorth)
    self.businessNum = aDecoder.decode(forKey: DMED.businessNum)
    self.generalEPM = aDecoder.decode(forKey: DMED.generalEPM)
    self.generalThreat = aDecoder.decode(forKey: DMED.generalThreat)
}

【讨论】:

    【解决方案3】:

    一种选择是编写一个允许键入密钥编码的包装器:

    struct KeyedNSCoder<Key : CodingKey> {
    
      let coder: NSCoder
    
      init(_ coder: NSCoder, keyedBy _: Key.Type) {
        self.coder = coder
      }
    
      func decodeDouble(forKey key: Key) -> Double {
        return coder.decodeDouble(forKey: key.stringValue)
      }
    
      func decodeInteger(forKey key: Key) -> Int {
        return coder.decodeInteger(forKey: key.stringValue)
      }
    
      // repeat for other coding methods...
    }
    

    那么你可以简单地说:

    enum DMED : String, CodingKey {
      case money = "DMMoney"
      case netWorth = "DMNetWorth"
      case businessNum = "DMBusinessNum"
      case generalEPM = "DMGeneralEPM"
      case generalThreat = "DMGeneralThreat"
    }
    
    class C : NSCoding {
    
      var money: Double // note: do not represent monetary values with floating-point numbers
      var netWorth: Double
      var businessNum: Int
      var generalEPM: Int
      var generalThreat: Int
    
      required init?(coder aDecoder: NSCoder) {
        let decoder = KeyedNSCoder(aDecoder, keyedBy: DMED.self)
        self.money = decoder.decodeDouble(forKey: .money)
        self.netWorth = decoder.decodeDouble(forKey: .netWorth)
        self.businessNum = decoder.decodeInteger(forKey: .businessNum)
        self.generalEPM = decoder.decodeInteger(forKey: .generalEPM)
        self.generalThreat = decoder.decodeInteger(forKey: .generalThreat)
      }
    
      func encode(with coder: NSCoder) {
        // ...
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多