사용자 지정 이니셜라이저가 있는 Swift 열거형은 rawValue 이니셜라이저를 잃게 됩니다.
저는 다음과 같이 이 문제를 가장 간단한 형태로 요약하려고 노력했습니다.
세우다
Xcode 버전 6.1.1(6A2008a)
다음에 정의된 열거형MyEnum.swift
:
internal enum MyEnum: Int {
case Zero = 0, One, Two
}
extension MyEnum {
init?(string: String) {
switch string.lowercaseString {
case "zero": self = .Zero
case "one": self = .One
case "two": self = .Two
default: return nil
}
}
}
그리고 다른 파일의 열거형을 초기화하는 코드,MyClass.swift
:
internal class MyClass {
let foo = MyEnum(rawValue: 0) // Error
let fooStr = MyEnum(string: "zero")
func testFunc() {
let bar = MyEnum(rawValue: 1) // Error
let barStr = MyEnum(string: "one")
}
}
오류
초기화를 시도할 때 Xcode에 다음 오류가 표시됩니다.MyEnum
원시 값 이니셜라이저 사용:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
메모들
-
원시 값 유형으로 열거형을 정의하면 열거형은 자동으로 원시 값 유형의 값을 사용하는 이니셜라이저를 수신합니다.
rawValue
) 및 열거 멤버 또는 를 반환합니다.nil
. 다음에 대한 사용자 정의 초기화자
MyEnum
Language Guide에서 다음과 같은 경우로 인해 열거형의 원시 값 이니셜라이저가 제거되는지 테스트하기 위해 확장에서 정의되었습니다.그러나 동일한 오류 결과를 얻을 수 있습니다.값 유형에 대한 사용자 정의 이니셜라이저를 정의하면 해당 유형에 대한 기본 이니셜라이저(또는 구조인 경우 멤버별 이니셜라이저)에 더 이상 액세스할 수 없습니다. [...]
사용자 정의 값 유형을 기본 이니셜라이저 및 멤버별 이니셜라이저와 함께 초기화할 수 있도록 하려면 사용자 정의 값 유형의 원래 구현의 일부가 아닌 확장에 사용자 정의 값 유형을 작성합니다.열거형 정의 이동
MyClass.swift
다음에 대한 오류 해결bar
하지만 때문은 아닙니다.foo
.사용자 지정 초기화 프로그램을 제거하면 두 오류가 모두 해결됩니다.
한 가지 해결 방법은 열거형 정의에 다음 함수를 포함하고 제공된 원시 값 이니셜라이저 대신 사용하는 것입니다.따라서 사용자 정의 이니셜라이저를 추가하면 원시 값 이니셜라이저를 표시하는 것과 유사한 효과가 있는 것 같습니다.
private
.init?(raw: Int) { self.init(rawValue: raw) }
다음에 대한 프로토콜 준수를 명시적으로 선언
RawRepresentable
에MyClass.swift
에 대한 인라인 오류 해결bar
그러나 중복 기호에 대한 링커 오류가 발생합니다(원시값 유형 열거형이 암시적으로 다음을 준수하기 때문).RawRepresentable
).extension MyEnum: RawRepresentable {}
여기서 무슨 일이 일어나고 있는지에 대해 좀 더 통찰력을 제공할 수 있는 사람이 있습니까?원시 값 이니셜라이저에 액세스할 수 없는 이유는 무엇입니까?
이 버그는 Xcode 7과 Swift 2에서 해결되었습니다.
extension TemplateSlotType {
init?(rawString: String) {
// Check if string contains 'carrousel'
if rawString.rangeOfString("carrousel") != nil {
self.init(rawValue:"carrousel")
} else {
self.init(rawValue:rawString)
}
}
}
이 경우 다음과 같은 확장이 발생합니다.
extension MyEnum {
init?(string: String) {
switch string.lowercaseString {
case "zero":
self.init(rawValue:0)
case "one":
self.init(rawValue:1)
case "two":
self.init(rawValue:2)
default:
return nil
}
}
}
코드를 더 단순하고 유용하게 만들 수도 있습니다.switch
케이스, 이렇게 하면 새 유형을 추가할 때 케이스를 추가할 필요가 없습니다.
enum VehicleType: Int, CustomStringConvertible {
case car = 4
case moped = 2
case truck = 16
case unknown = -1
// MARK: - Helpers
public var description: String {
switch self {
case .car: return "Car"
case .truck: return "Truck"
case .moped: return "Moped"
case .unknown: return "unknown"
}
}
static let all: [VehicleType] = [car, moped, truck]
init?(rawDescription: String) {
guard let type = VehicleType.all.first(where: { description == rawDescription })
else { return nil }
self = type
}
}
네, 이것은 성가신 문제입니다.저는 현재 공장 역할을 하는 글로벌 스코프 기능을 사용하여 작업하고 있습니다.
func enumFromString(string:String) -> MyEnum? {
switch string {
case "One" : MyEnum(rawValue:1)
case "Two" : MyEnum(rawValue:2)
case "Three" : MyEnum(rawValue:3)
default : return nil
}
}
이것은 내 EnumSequence와 함께 Xcode 9.2의 Swift 4에서 작동합니다.
enum Word: Int, EnumSequenceElement, CustomStringConvertible {
case apple, cat, fun
var description: String {
switch self {
case .apple:
return "Apple"
case .cat:
return "Cat"
case .fun:
return "Fun"
}
}
}
let Words: [String: Word] = [
"A": .apple,
"C": .cat,
"F": .fun
]
extension Word {
var letter: String? {
return Words.first(where: { (_, word) -> Bool in
word == self
})?.key
}
init?(_ letter: String) {
if let word = Words[letter] {
self = word
} else {
return nil
}
}
}
for word in EnumSequence<Word>() {
if let letter = word.letter, let lhs = Word(letter), let rhs = Word(letter), lhs == rhs {
print("\(letter) for \(word)")
}
}
산출량
A for Apple
C for Cat
F for Fun
코드에 추가합니다.
extension MyEnum {
init?(rawValue: Int) {
switch rawValue {
case 0: self = .Zero
case 1: self = .One
case 2: self = .Two
default: return nil
}
}
}
언급URL : https://stackoverflow.com/questions/27390989/swift-enum-with-custom-initializer-loses-rawvalue-initializer
'programing' 카테고리의 다른 글
Node.js 인증마다 사용할 환경별 구성 설정 (0) | 2023.07.31 |
---|---|
jQuery 템플릿 엔진 (0) | 2023.07.31 |
Oracle Forms 6i에서 웹으로 마이그레이션하는 데 가장 적합한 솔루션은 무엇입니까? (0) | 2023.07.31 |
탐색 컨트롤러 내부의 탭 모음 컨트롤러 또는 탐색 루트 보기 공유 (0) | 2023.07.31 |
온라인에서 C99 공용어 표준 설명서/참고 자료/사양서를 어디서 읽을 수 있습니까? (0) | 2023.07.31 |