【问题标题】:Swift enum both a string and an intSwift枚举字符串和int
【发布时间】:2015-04-12 05:23:06
【问题描述】:

我有一种情况,我正在尝试对某些数据进行二进制解码,并且数据类型同时具有数值和字符串值以及名称。我正在考虑使用枚举,例如:

enum TARGET_TRACK_TYPE : String {
    case TT_INVALID          = "Invalid"
    case TT_TRUE_TRACK_ANGLE = "True Track Angle"
    case TT_MAGNETIC         = "Magnetic"
    case TT_TRUE             = "True"
}

不过我也知道:

TT_INVALID = 0TT_TRUE_TRACK_ANGLE = 1 等。有没有一种简单的方法可以将字符串和数值这两个“东西”封装到一个枚举结构中,或者我需要制作某种结构/类来处理这个?

我想我想做一些类似的事情

let a = TARGET_TRACK_TYPE.rawValue(value: 2) println(a)

将打印True Track Angle

再次,我知道这可以通过结构或类来完成,但我对枚举特别感兴趣

或者再举个例子:

/// Emitter Category is defined in section 3.5.1.10 of the GDL90 Spec
struct EmitterCategory {

let category : Int

func getString() -> String {

    switch(category) {
    case 0:
        return "No aircraft type information";
    case 1:
        return "Light";
    case 2:
        return "Smalle";
    case 3:
        return "Large";
    case 4:
        return "High Vortex Large";
    case 5:
        return "Heavy";
    case 6:
        return "Highly Manuverable";
    case 7:
        return "Rotorcraft";
    case 8:
        return "(Unassigned)";
    case 9:
        return "Glider/sailplane";
    case 10:
        return "Ligther than air";
    case 11:
        return "Parachutist/sky diver";
    case 12:
        return "Ultra light/hang glider/paraglider";
    case 13:
        return "(Unassigned)";
    case 14:
        return "Unmanned aerial vehicle";
    case 15:
        return "Space/transatmospheric vehicle";
    case 16:
        return "(Unassigned)";
    case 17:
        return "Surface vehicle - emergency vehicle";
    case 18:
        return "Surface vehicle - service vehicle";
    case 19:
        return "Point obstacle";
    case 20:
        return "Cluster Obstacle";
    case 21:
        return "Line Obstacle";
    default:
        return "(reserved)";
    }
}
}

有没有办法将此结构重构为枚举,以便我用整数值构造枚举但我将枚举“读取”为字符串?我很确定答案是否定的。

【问题讨论】:

标签: swift enums


【解决方案1】:

我认为这会为我做这件事。谢谢你自己.. :)

protocol GDL90_Enum  {
      var description: String { get }
}

enum TARGET_ADDRESS_TYPE : Int, GDL90_Enum {
   case ADSB_ICAO_ADDRESS = 0
   case ADSB_SELF_ADDRESS = 1
   case TISB_ICAO = 2
   case TISB_TRACK_ID = 3
   case SURFACE_VEHICLE = 4
   case GROUND_STATION = 5

   var description: String {
      switch self {
   case .ADSB_ICAO_ADDRESS:
      return "ADS-B with ICAO address"
   case .ADSB_SELF_ADDRESS:
      return "ADS-B with Self-assigned address"
   case .TISB_ICAO:
      return "TIS-B with ICAO address"
   case .TISB_TRACK_ID:
         return "TIS-B with track file ID"
   case .SURFACE_VEHICLE:
         return "Surface Vehicle"
   case .GROUND_STATION:
         return "Ground Station Beacon"
   default:
         return "Reserved"
      }
   }
}

【讨论】:

【解决方案2】:

在 Swift 4.2 中,这可以使用 CaseIterable 来完成。一、比较简洁的方法是做如下

enum Directions: String, CaseIterable {
    case north, south, east, west

    static var asArray: [Directions] {return self.allCases}

    func asInt() -> Int {
        return Directions.asArray.firstIndex(of: self)!
    }
}

print(Directions.asArray[2])
// prints "east\n"

print(Directions.east.asInt())
// prints "2\n"

print(Directions.east.rawValue)
// prints "east\n"

【讨论】:

    【解决方案3】:

    你应该使用 RawRepresentable

    @objc enum AppEvent:Int, RawRepresentable  {
        case appLaunch
        case homeScreen
    
        public typealias RawValue = String
    
        public var rawValue: RawValue {
            switch self {
            case .appLaunch                      : return "appLaunch"
            case .homeScreen                    : return "homeScreen"
        }
    
        public init?(rawValue: RawValue) {
            switch rawValue {
            case "appLaunch"                    : self = .appLaunch
            case "homeScreen"                   : self = .homeScreen 
        }
    
    
    

    【讨论】:

      【解决方案4】:

      您是否考虑过使用字典?

       let targetTrackDict: [Int: String] =
            [99: "Invalid",
             1: "True Track Angle",
             2: "Magnetic",
             5: "True"]
      

      请注意,数字代码不必是有序的或连续的。在声明中具体说明字典的类型可以防止以下 sn-ps 中出现很多警告或错误。

      获取代码的名称很容易:

      var code = 2
      if let name = targetTrackDict[code] {
        print("\(name) has code \(code)")
      } else {
        print("\(code) is not a valid track type")
      }
      

      我还没有找到一种获取名称代码的简洁方法,但可以这样做:

      let magneticCode = targetTrackDict.first(where: 
          {key, value in value == "Magnetic"})?.key
      // returns an optional
      

      你当然会把它打扮成一个函数。您不会自动获得轨道类型的内部名称,但您需要一个吗?上面的代码在某种程度上为你做了。

      【讨论】:

        【解决方案5】:

        总结@Jeef 的回答和@NobodyNada 的评论,这里有一个解决方案

        public enum Animal: Int, CustomStringConvertible {
            case Dog, Cat
        
            public var description: String {
                switch self.rawValue {
                case 0: return "Dog"
                case 1: return "Cat"
                default: return ""
                }
            }
        }
        
        var animal = Animal.Dog
        print(animal) // Dog
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多