a, b, c, d 케이스가있는 열거 형이있는 경우 "a"문자열을 열거 형으로 캐스팅 할 수 있습니까?
답변:
확실한. 열거 형은 원시 값을 가질 수 있습니다. 문서를 인용하려면 :
원시 값은 문자열, 문자 또는 정수 또는 부동 소수점 숫자 유형일 수 있습니다.
— 발췌 : Apple Inc.“The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l ,
따라서 다음과 같은 코드를 사용할 수 있습니다.
enum StringEnum: String
{
case one = "one"
case two = "two"
case three = "three"
}
let anEnum = StringEnum(rawValue: "one")!
print("anEnum = \"\(anEnum.rawValue)\"")
참고 : 각 케이스 뒤에 = "one"등을 쓸 필요가 없습니다. 기본 문자열 값은 케이스 이름과 동일하므로 호출 .rawValue
하면 문자열이 반환됩니다.
케이스 값의 일부로 유효하지 않은 공백과 같은 것을 포함하기 위해 문자열 값이 필요한 경우 문자열을 명시 적으로 설정해야합니다. 그래서,
enum StringEnum: String
{
case one
case two
case three
}
let anEnum = StringEnum.one
print("anEnum = \"\(anEnum)\"")
준다
anEnum = "하나"
그러나 case
one
"값 1"을 표시하려면 문자열 값을 제공해야합니다.
enum StringEnum: String
{
case one = "value one"
case two = "value two"
case three = "value three"
}
Hashable
유형도 사용할 수 없습니다 .
case one = "uno"
. 이제 "one"
열거 형 값 으로 구문 분석하는 방법은 무엇입니까? (그들은 현지화에 사용하고 같은 RAWS를 사용할 수 없습니다)
= "one"
각 경우마다 등 을 쓸 필요가 없습니다 . 기본 문자열 값은 케이스 이름과 동일합니다.
필요한 것은 다음과 같습니다.
enum Foo: String {
case a, b, c, d
}
let a = Foo(rawValue: "a")
assert(a == Foo.a)
let 💩 = Foo(rawValue: "💩")
assert(💩 == nil)
Swift 4.2에서 CaseIterable 프로토콜은 rawValues가있는 열거 형에 사용될 수 있지만 문자열은 열거 형 케이스 레이블과 일치해야합니다.
enum MyCode : String, CaseIterable {
case one = "uno"
case two = "dos"
case three = "tres"
static func withLabel(_ label: String) -> MyCode? {
return self.allCases.first{ "\($0)" == label }
}
}
용법:
print(MyCode.withLabel("one")) // Optional(MyCode.one)
print(MyCode(rawValue: "uno")) // Optional(MyCode.one)
Int 유형이있는 열거 형의 경우 다음과 같이 할 수 있습니다.
enum MenuItem: Int {
case One = 0, Two, Three, Four, Five //... as much as needs
static func enumFromString(string:String) -> MenuItem? {
var i = 0
while let item = MenuItem(rawValue: i) {
if String(item) == string { return item }
i += 1
}
return nil
}
}
그리고 사용 :
let string = "Two"
if let item = MenuItem.enumFromString(string) {
//in this case item = 1
//your code
}
enumFromString
사용하는 각 열거 형에 대한 메서드를 작성하는 것은 미친 것 같습니다.
Duncan C의 답변 확장
extension StringEnum: StringLiteralConvertible {
init(stringLiteral value: String){
self.init(rawValue: value)!
}
init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
}
Swift 4.2 :
public enum PaymentPlatform: String, CaseIterable {
case visa = "Visa card"
case masterCard = "Master card"
case cod = "Cod"
var nameEnum: String {
return Mirror(reflecting: self).children.first?.label ?? String(describing: self)
}
func byName(name: String) -> PaymentPlatform {
return PaymentPlatform.allCases.first(where: {$0.nameEnum.elementsEqual(name)}) ?? .cod
}
}
Int enum 및 해당 문자열 표현의 경우 다음과 같이 enum을 선언합니다.
enum OrderState: Int16, CustomStringConvertible {
case waiting = 1
case inKitchen = 2
case ready = 3
var description: String {
switch self {
case .waiting:
return "Waiting"
case .inKitchen:
return "InKitchen"
case .ready:
return "Ready"
}
}
static func initialize(stringValue: String)-> OrderState? {
switch stringValue {
case OrderState.waiting.description:
return OrderState.waiting
case OrderState.inKitchen.description:
return OrderState.inKitchen
case OrderState.ready.description:
return OrderState.ready
default:
return nil
}
}
}
용법:
order.orderState = OrderState.waiting.rawValue
let orderState = OrderState.init(rawValue: order.orderState)
let orderStateStr = orderState?.description ?? ""
print("orderStateStr = \(orderStateStr)")
djruss70의 답변을 리핑하여 매우 일반화 된 솔루션을 만듭니다.
extension CaseIterable {
static func from(string: String) -> Self? {
return Self.allCases.first { string == "\($0)" }
}
func toString() -> String { "\(self)" }
}
용법:
enum Chassis: CaseIterable {
case pieridae, oovidae
}
let chassis: Chassis = Chassis.from(string: "oovidae")!
let string: String = chassis.toString()
참고 : enum이 @objc로 선언되면 안타깝게도 작동하지 않습니다. 내가 Swift 5.3에서 아는 한 무차별 대입 솔루션 (switch 문)을 제외하고 @objc enum과 함께 작동하도록 할 방법이 없습니다.
누군가 @objc 열거 형에 대해이 작업을 수행하는 방법을 알고 있다면 대답에 매우 관심이 있습니다.