Como posso determinar o número de casos em uma enumeração Swift?
(Gostaria de evitar enumerar manualmente todos os valores ou usar o antigo " truque enum_count ", se possível).
Como posso determinar o número de casos em uma enumeração Swift?
(Gostaria de evitar enumerar manualmente todos os valores ou usar o antigo " truque enum_count ", se possível).
No Swift 4.2 (Xcode 10), você pode declarar conformidade com o CaseIterable
protocolo, isso funciona para todas as enumerações sem valores associados:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
O número de casos agora é simplesmente obtido com
print(Stuff.allCases.count) // 4
Para mais informações, veja
Eu tenho um post de blog que entra em mais detalhes sobre isso, mas desde que o tipo bruto da sua enum seja um número inteiro, você pode adicionar uma contagem dessa maneira:
fonte
case A=1, B=3
?enum
ter umInt
valor bruto que você esqueceu de mencionar, há duas suposições : os swum enum com valores brutos Int não precisam começar de 0 (mesmo que esse seja o comportamento padrão) e seus valores brutos possam ser arbitrários, eles não têm para aumentar em 1 (mesmo que esse seja o comportamento padrão).Atualização do Xcode 10
Adote o
CaseIterable
protocolo no enum, ele fornece umaallCases
propriedade estática que contém todos os casos de enum como aCollection
. Basta usar suacount
propriedade para saber quantos casos o enum possui.Veja a resposta de Martin para um exemplo (e vote mais nas respostas dele do que nas minhas)
Aviso : o método abaixo parece não funcionar mais.
Não conheço nenhum método genérico para contar o número de casos enum. Notei, no entanto, que a
hashValue
propriedade dos casos enum é incremental, começando de zero e com a ordem determinada pela ordem em que os casos são declarados. Portanto, o hash do último enum mais um corresponde ao número de casos.Por exemplo, com esta enumeração:
count
retorna 4.Não posso dizer se isso é uma regra ou se alguma vez vai mudar no futuro, então use por sua conta e risco :)
fonte
hashValues
nessas coisas; tudo o que sabemos é que é algum valor exclusivo aleatório - pode mudar com muita facilidade no futuro, dependendo de alguns detalhes de implementação do compilador; mas, no geral, a falta de funcionalidade integrada de contagem é perturbadora.case ONE = 0
, poderá substituí-lohashValue
porrawValue
.static var count = 4
em vez de deixar o seu destino no destino de futuras implementações de SwiftDefino um protocolo reutilizável que executa automaticamente a contagem de casos com base na abordagem postada por Nate Cook.
Então eu posso reutilizar este protocolo, por exemplo, da seguinte maneira:
fonte
count++
decount+=1
uma vez++
notação será removido em Swift 3static var caseCount: Int { get }
? por que a necessidade destatic func
?case A=1, B=3
?0
e não tenham lacunas.Crie uma matriz estática allValues, como mostrado nesta resposta
Isso também é útil quando você deseja enumerar os valores e funciona para todos os tipos de Enum.
fonte
static let count = allValues.count
. Então você pode tornar oallValues
privado, se desejar.Se a implementação não tiver nada contra o uso de enumerações inteiras, você poderá adicionar um valor de membro extra chamado
Count
para representar o número de membros na enumeração - veja o exemplo abaixo:Agora você pode obter o número de membros na enum chamando,
TableViewSections.Count.rawValue
que retornará 2 para o exemplo acima.Ao manipular o enum em uma instrução switch, lembre-se de lançar uma falha de asserção ao encontrar o
Count
membro em que você não o espera:fonte
Esse tipo de função é capaz de retornar a contagem de sua enumeração.
Swift 2 :
Swift 3 :
fonte
enum
for do mesmo tipo.Hashable
contagem:
eEventTabType.allValues.count
índice:
objeEventTabType.index
Aproveitar :)
fonte
Oh, ei pessoal, e os testes de unidade?
Isso combinado com a solução de Antonio:
no código principal fornece O (1) e você obtém um teste com falha se alguém adicionar um caso de enum
five
e não atualizar a implementação decount
.fonte
Esta função depende do comportamento de 2 correntes não documentadas (Swift 1.1)
enum
:enum
é apenas um índice decase
. Se a contagem de casos for de 2 a 256, éUInt8
.enum
bit foi convertido a partir de um índice de caso inválido ,hashValue
é0
Portanto, use por sua conta e risco :)
Uso:
fonte
Eu escrevi uma extensão simples que fornece todas as enumerações em que o valor bruto é uma
count
propriedade inteira :Infelizmente, ele fornece a
count
propriedade paraOptionSetType
onde não funcionará corretamente, então aqui está outra versão que requer conformidade explícita com oCaseCountable
protocolo para qualquer enumeração de quais casos você deseja contar:É muito semelhante à abordagem postada por Tom Pelaia, mas funciona com todos os tipos de números inteiros.
fonte
Claro, não é dinâmico, mas para muitos usos, você pode conviver com uma var estática adicionada ao seu Enum
static var count: Int{ return 7 }
e depois use-o como
EnumName.count
fonte
OU
* No Swift 4.2 (Xcode 10) pode usar:
fonte
Para o meu caso de uso, em uma base de código em que várias pessoas podem adicionar chaves a uma enum, e esses casos devem estar disponíveis na propriedade allKeys, é importante que todas as chaves sejam validadas com relação às chaves na enum. Isso evita que alguém se esqueça de adicionar sua chave à lista de todas as chaves.A correspondência da contagem da matriz allKeys (criada primeiro como um conjunto para evitar enganos) com o número de chaves na enumeração garante que todas elas estejam presentes.
Algumas das respostas acima mostram o caminho para conseguir isso no Swift 2, mas nenhuma funciona no Swift 3 . Aqui está a versão formatada do Swift 3 :
Dependendo do seu caso de uso, convém executar o teste em desenvolvimento para evitar a sobrecarga do uso de allKeys em cada solicitação
fonte
Por que você torna tudo tão complexo? O contador SIMPLEST do Int enum é adicionar:
case Count
No final. E ... viola - agora você tem a contagem - rápido e simples
fonte
0
e não tenham lacunas na sequência.Se você não quiser basear seu código na última enumeração, poderá criar esta função dentro da enumeração.
fonte
Uma versão do Swift 3 trabalhando com
Int
enumerações de tipo:Créditos: Com base nas respostas de bzz e Nate Cook.
O genérico
IntegerType
(no Swift 3 renomeado paraInteger
) não é suportado, pois é um tipo genérico fortemente fragmentado que carece de muitas funções.successor
não está mais disponível no Swift 3.Esteja ciente de que o comentário da resposta do Code Commander a Nate Cooks ainda é válido:
Até onde eu sei, atualmente não há solução alternativa ao usá-lo como extensão de protocolo (e não implementar em cada enum como o Nate Cook) devido a propriedades armazenadas estáticas que não são suportadas em tipos genéricos.
De qualquer forma, para pequenas enumerações, isso não deve ser problema. Um caso de uso típico seria o
section.count
para,UITableViews
como já mencionado por Zorayr.fonte
Estendendo a resposta de Matthieu Riegler, esta é uma solução para o Swift 3 que não requer o uso de genéricos e pode ser facilmente chamada usando o tipo de enum com
EnumType.elementsCount
:fonte
Resolvi esse problema criando um protocolo (EnumIntArray) e uma função de utilitário global (enumIntArray) que facilitam a adição de uma variável "All" a qualquer enum (usando o swift 1.2). A variável "all" conterá uma matriz de todos os elementos na enumeração, para que você possa usar all.count para a contagem
Ele funciona apenas com enumerações que usam valores brutos do tipo Int, mas talvez possa fornecer alguma inspiração para outros tipos.
Ele também aborda a "lacuna na numeração" e o "tempo excessivo para iterar" os problemas que li acima e em outros lugares.
A idéia é adicionar o protocolo EnumIntArray à sua enum e definir uma variável estática "all" chamando a função enumIntArray e fornecer o primeiro elemento (e o último se houver lacunas na numeração).
Como a variável estática é inicializada apenas uma vez, a sobrecarga de passar por todos os valores brutos apenas atinge seu programa uma vez.
exemplo (sem lacunas):
exemplo (com lacunas):
Aqui está o código que o implementa:
fonte
Ou você pode simplesmente definir o
_count
exterior da enumeração e anexá-lo estaticamente:Dessa forma, não importa quantas enums você crie, ele será criado apenas uma vez.
(exclua esta resposta se
static
fizer isso)fonte
O método a seguir vem do CoreKit e é semelhante às respostas sugeridas por outras pessoas. Isso funciona com o Swift 4.
Então você só precisa ligar
Weekdays.allValues.count
.fonte
fonte
mas tenha cuidado com o uso em tipos não enum. Algumas soluções alternativas podem ser:
fonte
Ele pode usar uma constante estática que contém o último valor da enumeração mais um.
fonte
Isso é pequeno, mas acho que uma solução O (1) melhor seria a seguinte ( SOMENTE se sua enumeração estiver
Int
começando em x etc.):A resposta selecionada atualmente ainda acredito que seja a melhor para todas as enumerações, a menos que você esteja trabalhando com
Int
isso, recomendo esta solução.fonte
guard
é contraCOUNT
e gera um erro, retorna falso, etc. para resolver sua preocupação com a representação de tipos.