How to get the name of enumeration value in Swift?

前端 未结 12 1489
太阳男子
太阳男子 2020-11-29 23:53

If I have an enumeration with raw Integer values:

enum City: Int {
  case Melbourne = 1, Chelyabinsk, Bursa
}

let city = City.Melbourne
         


        
12条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-30 00:33

    As of Xcode 7 beta 5 (Swift version 2) you can now print type names and enum cases by default using print(_:), or convert to String using String's init(_:) initializer or string interpolation syntax. So for your example:

    enum City: Int {
        case Melbourne = 1, Chelyabinsk, Bursa
    }
    let city = City.Melbourne
    
    print(city)
    // prints "Melbourne"
    
    let cityName = "\(city)"   // or `let cityName = String(city)`
    // cityName contains "Melbourne"
    

    So there is no longer a need to define & maintain a convenience function that switches on each case to return a string literal. In addition, this works automatically for any enum, even if no raw-value type is specified.

    debugPrint(_:) & String(reflecting:) can be used for a fully-qualified name:

    debugPrint(city)
    // prints "App.City.Melbourne" (or similar, depending on the full scope)
    
    let cityDebugName = String(reflecting: city)
    // cityDebugName contains "App.City.Melbourne"
    

    Note that you can customise what is printed in each of these scenarios:

    extension City: CustomStringConvertible {
        var description: String {
            return "City \(rawValue)"
        }
    }
    
    print(city)
    // prints "City 1"
    
    extension City: CustomDebugStringConvertible {
        var debugDescription: String {
            return "City (rawValue: \(rawValue))"
        }
    }
    
    debugPrint(city)
    // prints "City (rawValue: 1)"
    

    (I haven't found a way to call into this "default" value, for example, to print "The city is Melbourne" without resorting back to a switch statement. Using \(self) in the implementation of description/debugDescription causes an infinite recursion.)


    The comments above String's init(_:) & init(reflecting:) initializers describe exactly what is printed, depending on what the reflected type conforms to:

    extension String {
        /// Initialize `self` with the textual representation of `instance`.
        ///
        /// * If `T` conforms to `Streamable`, the result is obtained by
        ///   calling `instance.writeTo(s)` on an empty string s.
        /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the
        ///   result is `instance`'s `description`
        /// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`,
        ///   the result is `instance`'s `debugDescription`
        /// * Otherwise, an unspecified result is supplied automatically by
        ///   the Swift standard library.
        ///
        /// - SeeAlso: `String.init(reflecting: T)`
        public init(_ instance: T)
    
        /// Initialize `self` with a detailed textual representation of
        /// `subject`, suitable for debugging.
        ///
        /// * If `T` conforms to `CustomDebugStringConvertible`, the result
        ///   is `subject`'s `debugDescription`.
        ///
        /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the result
        ///   is `subject`'s `description`.
        ///
        /// * Otherwise, if `T` conforms to `Streamable`, the result is
        ///   obtained by calling `subject.writeTo(s)` on an empty string s.
        ///
        /// * Otherwise, an unspecified result is supplied automatically by
        ///   the Swift standard library.
        ///
        /// - SeeAlso: `String.init(T)`
        public init(reflecting subject: T)
    }
    


    See the release notes for info about this change.

提交回复
热议问题