Swift从枚举中删除.rawValue

时间:2018-02-22 18:34:26

标签: swift enums

我有这个枚举:

mixin postList(stuff)
  .row
    - site.posts.each(function(post, index){
      .col-sm-12.col-md-6.col-lg-6.col-xl-4
        .card.my-3
          img.card-img-top(src="...",  alt="Card image cap")
          .card-body
            h5.card-title Card title #{index}
            p.card-text Some quick example text to build on the card title and make up the bulk of the cards content.
            a.btn.btn-primary(href="#") Go somewhere
    - })

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

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

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

3 个答案:

答案 0 :(得分:0)

如果您仅使用enum值,那么它们可用作String常量,则应更改代码以使用struct static值。

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))
}

答案 1 :(得分:0)

您可以在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)

或者,如果您想使方法更通用,并使用任何String枚举,您可以使方法覆盖泛型:

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)
}

答案 2 :(得分:0)

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

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) {
    // ...
  }
}