Tentei reduzir esse problema à sua forma mais simples com o seguinte.
Configuração
Xcode versão 6.1.1 (6A2008a)
Um enum definido em 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
}
}
}
e o código que inicializa o enum em outro arquivo 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")
}
}
Erro
O Xcode me dá o seguinte erro ao tentar inicializar MyEnum
com seu inicializador de valor bruto:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
Notas
De acordo com o Guia de Idiomas Swift :
Se você definir uma enumeração com um tipo de valor bruto, a enumeração receberá automaticamente um inicializador que recebe um valor do tipo do valor bruto (como um parâmetro chamado
rawValue
) e retorna um membro de enumeração ounil
.O inicializador personalizado para
MyEnum
foi definido em uma extensão para testar se o inicializador de valor bruto do enum estava sendo removido devido ao seguinte caso do Guia de Idiomas . No entanto, ele obtém o mesmo resultado de erro.Observe que se você definir um inicializador personalizado para um tipo de valor, não terá mais acesso ao inicializador padrão (ou ao inicializador de membro, se for uma estrutura) para esse tipo. [...]
Se você deseja que seu tipo de valor customizado seja inicializável com o inicializador padrão e o inicializador de membro, e também com seus próprios inicializadores customizados, escreva seus inicializadores customizados em uma extensão em vez de como parte da implementação original do tipo de valor.Mover a definição de enum para
MyClass.swift
resolver o erro para,bar
mas não parafoo
.Remover o inicializador personalizado resolve os dois erros.
Uma solução alternativa é incluir a função a seguir na definição de enum e usá-la no lugar do inicializador de valor bruto fornecido. Portanto, parece que adicionar um inicializador personalizado tem um efeito semelhante a marcar o inicializador de valor bruto
private
.init?(raw: Int) { self.init(rawValue: raw) }
Declarar explicitamente a conformidade do protocolo com
RawRepresentable
emMyClass.swift
resolve o erro embutido parabar
, mas resulta em um erro do vinculador sobre símbolos duplicados (porque enums de tipo de valor bruto estão implicitamente em conformidade comRawRepresentable
).extension MyEnum: RawRepresentable {}
Alguém pode fornecer mais informações sobre o que está acontecendo aqui? Por que o inicializador de valor bruto não está acessível?
internal
escopo (ou pelo menos corresponder ao tipo), nãoprivate
.Respostas:
Este bug é resolvido no Xcode 7 e Swift 2
fonte
No seu caso, isso resultaria na seguinte extensão:
fonte
Você pode até tornar o código mais simples e útil sem
switch
casos, dessa forma você não precisa adicionar mais casos ao adicionar um novo tipo.fonte
Sim, este é um problema irritante. Atualmente, estou trabalhando nisso usando uma função de escopo global que atua como uma fábrica, ou seja,
fonte
Isso funciona para Swift 4 no Xcode 9.2 junto com meu EnumSequence :
Resultado
fonte
Adicione isto ao seu código:
fonte