He intentado resumir este problema en su forma más simple con lo siguiente.
Preparar
Versión de Xcode 6.1.1 (6A2008a)
Una enumeración definida en 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
}
}
}
y el código que inicializa la enumeración en otro archivo, 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")
}
}
Error
Xcode me da el siguiente error al intentar inicializar MyEnum
con su inicializador de valor sin procesar:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
Notas
Según la guía de idiomas Swift :
Si define una enumeración con un tipo de valor sin formato, la enumeración recibe automáticamente un inicializador que toma un valor del tipo del valor sin formato (como un parámetro llamado
rawValue
) y devuelve un miembro de enumeración onil
.El inicializador personalizado para
MyEnum
se definió en una extensión para probar si el inicializador de valor sin formato de la enumeración se estaba quitando debido al siguiente caso de la Guía del idioma . Sin embargo, logra el mismo resultado de error.Tenga en cuenta que si define un inicializador personalizado para un tipo de valor, ya no tendrá acceso al inicializador predeterminado (o al inicializador por miembros, si es una estructura) para ese tipo. [...]
Si desea que su tipo de valor personalizado sea inicializable con el inicializador predeterminado y el inicializador por miembros, y también con sus propios inicializadores personalizados, escriba sus inicializadores personalizados en una extensión en lugar de como parte de la implementación original del tipo de valor.Mover la definición de enumeración a
MyClass.swift
resuelve el error parabar
pero no parafoo
.La eliminación del inicializador personalizado resuelve ambos errores.
Una solución es incluir la siguiente función en la definición de enumeración y usarla en lugar del inicializador de valor sin formato proporcionado. Por lo tanto, parece que agregar un inicializador personalizado tiene un efecto similar al de marcar el inicializador de valor sin procesar
private
.init?(raw: Int) { self.init(rawValue: raw) }
Declarar explícitamente la conformidad del protocolo con
RawRepresentable
inMyClass.swift
resuelve el error en línea debar
, pero da como resultado un error del enlazador sobre símbolos duplicados (porque las enumeraciones de tipo de valor sin procesar se ajustan implícitamente aRawRepresentable
).extension MyEnum: RawRepresentable {}
¿Alguien puede proporcionar un poco más de información sobre lo que está sucediendo aquí? ¿Por qué no se puede acceder al inicializador de valor bruto?
internal
alcance (o al menos coincidir con el tipo), noprivate
.Respuestas:
Este error se resuelve en Xcode 7 y Swift 2
fuente
En su caso, esto resultaría en la siguiente extensión:
fuente
Incluso puede hacer que el código sea más simple y útil sin
switch
casos, de esta manera no necesita agregar más casos cuando agrega un nuevo tipo.fuente
Sí, este es un problema molesto. Actualmente estoy trabajando en ello usando una función de alcance global que actúa como una fábrica, es decir
fuente
Esto funciona para Swift 4 en Xcode 9.2 junto con mi EnumSequence :
Salida
fuente
Agregue esto a su código:
fuente