Spróbowałem sprowadzić ten problem do jego najprostszej formy w następujący sposób.
Ustawiać
Xcode w wersji 6.1.1 (6A2008a)
Wyliczenie zdefiniowane w 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
}
}
}
i kod, który inicjuje wyliczenie w innym pliku 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")
}
}
Błąd
Xcode wyświetla następujący błąd podczas próby zainicjowania MyEnumprzy użyciu inicjalizatora surowej wartości:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
Uwagi
Według przewodnika Swift Language :
Jeśli zdefiniujesz wyliczenie z typem wartości surowej, wyliczenie automatycznie otrzyma inicjator, który przyjmuje wartość typu wartości surowej (jako wywoływany parametr
rawValue) i zwraca element członkowski wyliczenia lubnil.Niestandardowy inicjator dla
MyEnumzostał zdefiniowany w rozszerzeniu w celu sprawdzenia, czy inicjator wartości surowej wyliczenia został usunięty z powodu następującego przypadku z przewodnika językowego . Jednak osiąga ten sam wynik błędu.Zwróć uwagę, że jeśli zdefiniujesz niestandardowy inicjator dla typu wartości, nie będziesz już mieć dostępu do domyślnego inicjatora (lub inicjatora elementu członkowskiego, jeśli jest to struktura) dla tego typu. [...]
Jeśli chcesz, aby niestandardowy typ wartości był inicjalizowany za pomocą domyślnego inicjatora i elementu członkowskiego, a także za pomocą własnych niestandardowych inicjatorów, napisz niestandardowe inicjatory w rozszerzeniu, a nie jako część oryginalnej implementacji typu wartości.Przeniesienie definicji wyliczenia do
MyClass.swiftrozwiązania błędu dla,barale nie dlafoo.Usunięcie niestandardowego inicjatora rozwiązuje oba błędy.
Jednym obejściem jest uwzględnienie następującej funkcji w definicji wyliczenia i użycie jej zamiast podanego inicjatora wartości surowej. Wygląda więc na to, że dodanie niestandardowego inicjatora ma podobny efekt, jak oznaczenie inicjalizatora surowej wartości
private.init?(raw: Int) { self.init(rawValue: raw) }Jawne zadeklarowanie zgodności protokołu z
RawRepresentableinMyClass.swiftrozwiązuje błąd wbudowany dlabar, ale powoduje błąd konsolidatora dotyczący zduplikowanych symboli (ponieważ wyliczenia typu surowej wartości są niejawnie zgodne zRawRepresentable).extension MyEnum: RawRepresentable {}
Czy ktoś może podać trochę więcej informacji o tym, co się tutaj dzieje? Dlaczego inicjator wartości nieprzetworzonych nie jest dostępny?
internalzasięg (lub przynajmniej pasować do typu), a nieprivate.