원시 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
사용하여 변환 할 수 있습니다. 예를 들어 :String
init(_:)
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)
구현에 사용 하면 무한 재귀가 발생합니다.)description
debugDescription
위 String
의 init(_:)
& 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"
}
}
}
그런 다음 enum
as 를 캐스팅하십시오 String
.
String(UIDevice.currentDevice().batteryState)
답변
String(describing:)
초기화 심지어 비 문자열 rawValues와 열거 형의 경우 레이블 이름을 반환 할 수 있습니다 :
enum Numbers: Int {
case one = 1
case two = 2
}
let one = String(describing: Numbers.one) // "one"
let two = String(describing: Numbers.two) // "two"
이 점에 유의 작동하지 않습니다 열거가 사용하는 경우 @objc
수정을 :
Objective-C 유형에 대해 생성 된 Swift 인터페이스에는 때때로 @objc
수정자가 포함되지 않습니다 . 그럼에도 불구하고 이러한 열거 형은 Objective-C에 정의되어 있으므로 위와 같이 작동하지 않습니다.
답변
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"
그러나 깨져서 “단순한”열거 형의 경우 위의 반사 기반 label
계산 속성은 nil
(boo-hoo)를 반환합니다 .
print(City.Chelyabinsk.label) // prints out nil
Swift 3 이후에는 반성이있는 상황이 좋아질 것입니다. String(…)
다른 답변 중 하나에서 제안한 것처럼 지금의 해결책은입니다 .
print(String(City.Chelyabinsk)) // prints out Cheylabinsk
답변
너무 실망 스럽습니다.
그러한 이름이 필요한 경우 (컴파일러는 정확한 철자를 완벽하게 알고 있지만 액세스를 거부합니다-Swift 팀 감사합니다 !!)-String을 열거 형의 기초로 만들고 싶지는 않습니다. 장황하고 번거로운 대안은 다음과 같습니다.
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()
}
}
}
위와 같이 사용할 수 있습니다 :
let elementType = ViewType.Title
let column = Column.Collections
let row = 0
println("fetching element \(elementType), column: \(column.string()), row: \(row)")
그리고 예상 결과를 얻습니다 (열의 코드는 비슷하지만 표시되지는 않음)
fetching element Title, column: Collections, row: 0
위에서, 나는 description
속성이 string
방법을 다시 참조하도록 만들었지 만 이것은 맛의 문제입니다. 또한 static
컴파일러는 너무 기억 상실하고 컨텍스트 자체를 리콜 할 수 없으므로 소위 변수는 엔 클로징 유형의 이름으로 범위를 한정해야합니다.
스위프트 팀은 반드시 지휘해야합니다. 그들은 당신이 할 수없는 열거 생성 enumerate
되는 것을 사용할 수 enumerate
있지만 페이지의 “시퀀스”됩니다 enum
!