Programing

Swift에서 열거 형 값의 이름을 얻는 방법은 무엇입니까?

lottogame 2020. 6. 17. 20:26
반응형

Swift에서 열거 형 값의 이름을 얻는 방법은 무엇입니까?


원시 Integer값으로 열거 형이있는 경우 :

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

let city = City.Melbourne

city값을 문자열 로 어떻게 변환 Melbourne합니까? 이런 종류의 이름 내성 검사가 언어로 제공됩니까?

다음과 같은 것 (이 코드는 작동하지 않습니다) :

println("Your city is \(city.magicFunction)")
> Your city is Melbourne

Xcode 7 베타 5 (Swift 버전 2)부터는 기본적으로을 사용하여 유형 이름과 열거 형 케이스를 인쇄 print(_:)하거나 이니셜 라이저 또는 문자열 보간 구문 String사용하여 변환 할 수 있습니다. 예를 들어,Stringinit(_:)

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"

따라서 더 이상 문자열 리터럴을 리턴하기 위해 각 케이스를 전환하는 편의 기능을 정의하고 유지 보수 할 필요가 없습니다. 또한 이는 원시 값 유형이 지정되지 않은 경우에도 모든 열거 형에 대해 자동으로 작동합니다.

debugPrint(_:)& String(reflecting:)는 완전한 이름으로 사용될 수 있습니다 :

debugPrint(city)
// prints "App.City.Melbourne" (or similar, depending on the full scope)

let cityDebugName = String(reflecting: city)
// cityDebugName contains "App.City.Melbourne"

다음 각 시나리오에서 인쇄되는 내용을 사용자 정의 할 수 있습니다.

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

(이 스위치 값에 의존하지 않고 "도시는 멜버른"으로 인쇄하는 것과 같이이 "기본"값을 호출하는 방법을 찾지 못했습니다. / \(self)구현에 사용 하면 무한 재귀가 발생합니다.)descriptiondebugDescription


Stringinit(_:)& init(reflecting:)이니셜 라이저는 반영된 유형이 준수하는 내용에 따라 인쇄되는 내용을 정확하게 설명합니다.

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<T>(reflecting: T)`
    public init<T>(_ 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>(T)`
    public init<T>(reflecting subject: T)
}


이 변경에 대한 정보 릴리스 정보참조하십시오 .


현재 열거 형 사례에 대한 내성은 없습니다. 각각 수동으로 선언해야합니다.

enum City: String, CustomStringConvertible {
    case Melbourne = "Melbourne"
    case Chelyabinsk = "Chelyabinsk"
    case Bursa = "Bursa"

    var description: String {
        get {
            return self.rawValue
        }
    }
}

원시 유형이 Int가되어야하는 경우 직접 스위치를 수행해야합니다.

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

  var description: String {
    get {
      switch self {
        case .Melbourne:
          return "Melbourne"
        case .Chelyabinsk:
          return "Chelyabinsk"
        case .Bursa:
          return "Bursa"
      }
    }
  }
}

Swift-3 (Xcode 8.1로 테스트)에서 열거 형에 다음 메소드를 추가 할 수 있습니다.

/**
 * The name of the enumeration (as written in case).
 */
var name: String {
    get { return String(describing: self) }
}

/**
 * The full name of the enumeration
 * (the name of the enum plus dot plus the name as written in case).
 */
var description: String {
    get { return String(reflecting: self) }
}

그런 다음 열거 형 인스턴스에서 일반적인 메소드 호출로 사용할 수 있습니다. 이전 Swift 버전에서도 작동하지만 테스트하지는 않았습니다.

귀하의 예에서 :

enum City: Int {
    case Melbourne = 1, Chelyabinsk, Bursa
    var name: String {
        get { return String(describing: self) }
    }
    var description: String {
        get { return String(reflecting: self) }
    }
}
let city = City.Melbourne

print(city.name)
// prints "Melbourne"

print(city.description)
// prints "City.Melbourne"

이 기능을 모든 열거 형에 제공하려는 경우이를 확장으로 만들 수 있습니다.

/**
 * Extend all enums with a simple method to derive their names.
 */
extension RawRepresentable where RawValue: Any {
  /**
   * The name of the enumeration (as written in case).
   */
  var name: String {
    get { return String(describing: self) }
  }

  /**
   * The full name of the enumeration
   * (the name of the enum plus dot plus the name as written in case).
   */
  var description: String {
    get { return String(reflecting: self) }
  }
}

이것은 Swift 열거 형에서만 작동합니다.


Objective-C enum의 경우 현재 예를 들어 CustomStringConvertible다음과 같이 끝나는 열거 형을 확장하는 유일한 방법 인 것 같습니다.

extension UIDeviceBatteryState: CustomStringConvertible {
    public var description: String {
        switch self {
        case .Unknown:
            return "Unknown"
        case .Unplugged:
            return "Unplugged"
        case .Charging:
            return "Charging"
        case .Full:
            return "Full"
        }
    }
}

그런 다음 enumas 를 캐스팅하십시오 String.

String(UIDevice.currentDevice().batteryState)

Swift 2.2의 열거 형에 대한 String (…) (CustomStringConvertible) 지원 외에도 약간의 리플렉션 지원이 있습니다. 관련 값이있는 열거 형 케이스의 경우 리플렉션을 사용하여 열거 형 케이스의 레이블을 가져올 수 있습니다.

enum City {
    case Melbourne(String)
    case Chelyabinsk
    case Bursa

    var label:String? {
        let mirror = Mirror(reflecting: self)
        return mirror.children.first?.label
    }
}

print(City.Melbourne("Foobar").label) // prints out "Melbourne"

By being broken, I however meant that for "simple" enums, the above reflection based label computed property just returns nil (boo-hoo).

print(City.Chelyabinsk.label) // prints out nil

The situation with reflection should be getting better after Swift 3, apparently. The solution for now though is String(…), as suggested in one of the other answers:

print(String(City.Chelyabinsk)) // prints out Cheylabinsk

This is so disappointing.

For the case when you need those names (that the compiler perfectly knows the exact spelling of, but refuses to let access -- thank you Swift team!! --) but do not want or cannot make String the base of your enum, a verbose, cumbersome alternative is as follows:

enum ViewType : Int, Printable {

    case    Title
    case    Buttons
    case    View

    static let all = [Title, Buttons, View]
    static let strings = ["Title", "Buttons", "View"]

    func string() -> String {
        return ViewType.strings[self.rawValue]
    }

    var description:String {
        get {
            return string()
        }
    }
}

You can use the above as follows:

let elementType = ViewType.Title
let column = Column.Collections
let row = 0

println("fetching element \(elementType), column: \(column.string()), row: \(row)")

And you'll get the expected result (code for the Column similar, but not shown)

fetching element Title, column: Collections, row: 0

In the above, I have made the description property refer back to the string method, but this is a matter of taste. Also note that so called static variables need to be scope qualified by the name of their enclosing type, as the compiler is too amnesic and cannot recall the context all by itself...

The Swift team must really be commanded. They created enum that you cannot enumerate and that which you can use enumerate on are "Sequences" but not enum!


For Swift:

extension UIDeviceBatteryState: CustomStringConvertible {

    public var description: String {
        switch self {
        case .unknown:
            return "unknown"
        case .unplugged:
            return "unplugged"
        case .charging:
            return "charging"
        case .full:
            return "full"
        }
    }

}

if your variable "batteryState" then call:

self.batteryState.description

Swift now has what are known as Implicitly Assigned Raw Value. Basically if you don't give raw values to each case and the enum is of type String, it deduces that the case's raw value is itself in string format. Go on give it a try.

enum City: String {
  case Melbourne, Chelyabinsk, Bursa
}

let city = City.Melbourne.rawValue

// city is "Melbourne"

The String(describing:) initializer can be used to return the case label name even for enums with non-String rawValues:

enum Numbers: Int {
    case one = 1
    case two = 2
}

let one = String(describing: Numbers.one) // "one"
let two = String(describing: Numbers.two) // "two"

Note that this does not work if the enum uses the @objc modifier:

https://forums.swift.org/t/why-is-an-enum-returning-enumname-rather-than-caselabel-for-string-describing/27327

Generated Swift interfaces for Objective-C types sometimes do not include the @objc modifier. Those Enums are nevertheless defined in Objective-C, and thus do not work like above.


Simple but works...

enum ViewType : Int {
    case    Title
    case    Buttons
    case    View
}

func printEnumValue(enum: ViewType) {

    switch enum {
    case .Title: println("ViewType.Title")
    case .Buttons: println("ViewType.Buttons")
    case .View: println("ViewType.View")
    }
}

참고URL : https://stackoverflow.com/questions/24113126/how-to-get-the-name-of-enumeration-value-in-swift

반응형