Я попытался свести эту проблему к простейшей форме следующим образом.
Настроить
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?'
Ноты
Согласно Swift Language Guide :
Если вы определяете перечисление с типом необработанного значения, перечисление автоматически получает инициализатор, который принимает значение типа необработанного значения (как вызываемый параметр
rawValue) и возвращает либо член перечисления, либоnil.Пользовательский инициализатор для
MyEnumбыл определен в расширении, чтобы проверить, удалялся ли инициализатор необработанного значения перечисления из-за следующего случая из Language Guide . Однако он дает тот же результат ошибки.Обратите внимание: если вы определяете настраиваемый инициализатор для типа значения, у вас больше не будет доступа к инициализатору по умолчанию (или поэлементному инициализатору, если это структура) для этого типа. [...]
Если вы хотите, чтобы ваш настраиваемый тип значения был инициализирован с помощью инициализатора по умолчанию и поэлементного инициализатора, а также с вашими собственными настраиваемыми инициализаторами, напишите свои настраиваемые инициализаторы в расширении, а не как часть исходной реализации типа значения.Перемещение определения перечисления для
MyClass.swiftустранения ошибки для,barно не дляfoo.Удаление настраиваемого инициализатора устраняет обе ошибки.
Один из способов обхода - включить следующую функцию в определение перечисления и использовать ее вместо предоставленного инициализатора необработанного значения. Таким образом, кажется, что добавление настраиваемого инициализатора имеет тот же эффект, что и маркировка инициализатора необработанного значения
private.init?(raw: Int) { self.init(rawValue: raw) }Явное объявление соответствия протокола
RawRepresentableinMyClass.swiftразрешает встроенную ошибку дляbar, но приводит к ошибке компоновщика, связанной с повторяющимися символами (поскольку перечисления типов с необработанными значениями неявно соответствуютRawRepresentable).extension MyEnum: RawRepresentable {}
Может ли кто-нибудь дать немного больше информации о том, что здесь происходит? Почему недоступен инициализатор необработанного значения?
internalобласть видимости (или, по крайней мере, соответствовать типу), а неprivate.