Int-Enum to String and vice a versa in Swift I have a situation in my client-server app where I have to send my network strength to server and also receive other clients' strength from server.

So I created enum as:

enum NetworkType: Int {
    case none, gprs, two_g, three_g, four_g, lte, wifi
}
extension NetworkType: Comparable {
    public static func &lt; (a: NetworkType, b: NetworkType) -&gt; Bool {
        return a.rawValue &lt; b.rawValue
    }
}


I can use this as:

if NetworkType.two_g &lt; NetworkType.three_g { 
    print("low network") 
}


But for sending to server, I have to convert it to String and vice a versa.
So I added one more extension as:

extension NetworkType {

    static var networkDict: [String: NetworkType] = ["gprs": .gprs,
                                                     "2g": .two_g,
                                                     "3g": .three_g,
                                                     "4g": .four_g,
                                                     "lte": .lte,
                                                     "wifi": .wifi];
    init(rawString: String) {
        let loweredStr = rawString.lowercased()
        self = NetworkType.networkDict[loweredStr] ?? .none
    }

    func rawString() -&gt; String? {
        return NetworkType.networkDict.allKeys(forValue: self).first
    }
}

//Dictionary extension for 'key for value'
extension Dictionary where Value: Equatable {
    func allKeys(forValue val: Value) -&gt; [Key] {
        return self.filter { $1 == val }.map { $0.0 }
    }
}

let network = NetworkType(rawString: "gprs") //gprs, while receiving from server
let rawString = NetworkType.gprs.rawString() //"gprs", while sending to server


It is working fine, no issues.
Jus curious to know if theres any better way to achieve this.
Is the .none case really needed? It serves as a "fallback" in init(rawString: String)
if an unknown string is received from the network. But it is not listed in
the mapping dictionary, i.e. it can not be converted back to a string.

My suggestion is to remove that case, and use a failable initializer for the 
conversion from a string:

init?(rawString: String) {
    let loweredStr = rawString.lowercased()
    guard let type = NetworkType.networkDict[loweredStr] else {
        return nil
    }
    self = type
}


Using a custom extension for the conversion to a string is not really necessary,
the same can be achieved directly with

func rawString() -&gt; String? {
    return NetworkType.networkDict.first(where: { $1 == self }).map { $0.0 }
}


But the real question is: Why does this return an optional? It would return nil
if one of the enum cases is not covered in the dictionary. Let us assume that
you add another case five_g in the enumeration and forget to update the dictionary.
Now NetworkType.five_g.rawString() returns nil. What string do you send to the
server? 

One possible approach would be to force-unwrap the string, so that this
programming error is detected early:

func rawString() -&gt; String {
    return NetworkType.networkDict.first(where: { $1 == self }).map { $0.0 }!
}


But there is still a chance that the error remains undetected during development
and the deployed application crashes later.



A safer (and actually shorter and easier) approach is to define a string-based
enumeration, which implicitly defines the conversion to strings
and back:

enum NetworkType: String {
    case gprs
    case two_g = "2g"
    case three_g = "3g"
    case four_g = "4g"
    case lte
    case wifi
}


To make the comparison work, an ordinal number is associated with 
each case:

extension NetworkType: Comparable {
    var ordinal: Int {
        switch self {
        case .gprs: return 1
        case .two_g: return 2
        case .three_g: return 3
        case .four_g: return 4
        case .lte: return 5
        case .wifi: return 6
        }
    }

    public static func &lt; (a: NetworkType, b: NetworkType) -&gt; Bool {
        return a.ordinal &lt; b.ordinal
    }
}


Now the conversion is done using the built-in methods:

// String to NetworkType:
if let network = NetworkType(rawValue: "gprs") {
    // ..
} else {
    // unknown string from network
}

// NetworkType to String:
let rawString = NetworkType.gprs.rawValue


The conversion to a string cannot fail anymore. If another case is added, the compiler ensures that it is added to var ordinal as well.