Supondo que eu tenha um typedef declarado no meu arquivo .h como tal:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Gostaria de criar uma função que converte o valor numérico do typedef em uma string. Por exemplo, se a mensagem [self toString:JSON]
foi enviada; retornaria 'JSON'.
A função ficaria assim:
-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}
Aliás, se eu tentar esta sintaxe
[self toString:FormatType.JSON];
para passar o valor typedef para o método, recebo um erro. o que estou perdendo?
c
objective-c
enums
typedef
craig
fonte
fonte
Respostas:
Esta é realmente uma pergunta em C, não específica ao Objective-C (que é um superconjunto da linguagem C). Enums em C são representados como números inteiros. Portanto, você precisa escrever uma função que retorne uma string com um valor enum. Há muitas maneiras de fazer isso. Uma matriz de seqüências de caracteres, de modo que o valor de enum possa ser usado como um índice para a matriz ou uma estrutura de mapa (por exemplo, uma
NSDictionary
) que mapeia um valor de enum para um trabalho de string, mas acho que essas abordagens não são tão claras quanto uma função que torna a conversão explícita (e a abordagem de matriz, embora aC
maneira clássica seja perigosa se seus valores de enumeração não forem contíguos de 0). Algo assim funcionaria:Sua pergunta relacionada sobre a sintaxe correta para um valor de enum é que você usa apenas o valor (por exemplo
JSON
), não aFormatType.JSON
sintaxe.FormatType
é um tipo e os valores enum (por exemploJSON
,XML
, etc.) são os valores que você pode atribuir a esse tipo.fonte
Você não pode fazer isso facilmente. Em C e Objective-C, enums são realmente apenas constantes inteiras glorificadas. Você terá que gerar uma tabela de nomes por conta própria (ou com algum abuso do pré-processador). Por exemplo:
O perigo dessa abordagem é que, se você alterar o enum, lembre-se de alterar a matriz de nomes. Você pode resolver esse problema com algum abuso do pré-processador, mas é complicado e feio.
Observe também que isso pressupõe que você tenha uma constante de enumeração válida. Se você possui um valor inteiro de uma fonte não confiável, você também precisa verificar se sua constante é válida, por exemplo, incluindo um valor "passado máximo" em sua enumeração ou verificando se é menor que o comprimento da matriz
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
.fonte
string[] = { [XML] = "XML" }
para garantir que a corda igualar os enums corretamenteFormatType_toString[]
matriz e chamar-isEqualToString:
cada elemento para encontrar uma correspondência ou usar um tipo de dados de mapeamento, comoNSDictionary
para manter o mapa de pesquisa inversa.FormatType_toString
matriz.Minha solução:
edit: adicionei uma solução ainda melhor no final, usando o Modern Obj-C
1.
Coloque os nomes como chaves em uma matriz.
Verifique se os índices são as enumerações apropriadas e na ordem correta (caso contrário, exceção).
nota: names é uma propriedade sintetizada como * _names *;
o código não foi verificado para compilação, mas usei a mesma técnica no meu aplicativo.
//
2.
Usando o Obj-C moderno, podemos usar um dicionário para vincular descrições às chaves na enumeração.
A ordem NÃO importa .
Uso (em um método de instância de classe):
fonte
+[typeDisplayNames]
, está recriando o dicionário. Isso é bom se for chamado apenas algumas vezes, mas se for chamado várias vezes, ficará muito caro. Uma solução melhor pode ser tornar o dicionário um singleton, para que ele seja criado apenas uma vez e permaneça na memória caso contrário. Memória clássica vs. enigma da CPU.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
Comentários não permitirão quebras de linha, desculpe por isso.Combinando a resposta @AdamRosenfield, o comentário @Christoph e outro truque para lidar com enums C simples, sugiro:
Na pior das hipóteses - como se você alterar o enum, mas se esquecer de alterar a matriz de nomes -, ele retornará nulo para essa chave.
fonte
defina typedef enum no cabeçalho da classe:
escreva um método como este na classe:
tem as strings dentro do arquivo Localizable.strings :
fonte
Eu usaria o token de string # do compilador (junto com macros para torná-lo mais compacto):
fonte
eu gosto de
#define
maneira de fazer isso:// Coloque isso no seu arquivo .h, fora do bloco @interface
fonte(fonte não está mais disponível)fonte
nil
searray.count <= enumValue
?Eu fiz uma espécie de combinação de todas as soluções encontradas nesta página para criar as minhas, é um tipo de extensão de enumeração orientada a objetos ou algo assim.
De fato, se você precisar de mais do que constantes (ou seja, números inteiros), provavelmente precisará de um objeto de modelo (todos nós estamos falando sobre MVC, certo?)
Basta fazer a si mesmo a pergunta antes de usar isso, estou certo, de fato, você não precisa de um objeto de modelo real, inicializado a partir de um serviço da web, um plist, um banco de dados SQLite ou CoreData?
De qualquer forma, aqui vem o código (MPI é para "My Project Initials", todo mundo usa esse ou seu nome, ao que parece):
MyWonderfulType.h
:E
MyWonderfulType.m
:fonte
Outra solução:
No seu método, você pode usar:
fonte
Resposta aprimorada @ yar1vn eliminando a dependência de string:
Assim, quando você alterar o nome da entrada do enum, a sequência correspondente será alterada. Útil no caso de você não mostrar essa string ao usuário.
fonte
"foo""bar"
, isso resulta na cadeia"foobar"
quando compilada. Então,#define VariableName(arg) (@""#arg)
vai se expandirVariableName(MyEnum)
para ser(@"""MyEnum")
. Isso resultará na string@"MyEnum"
.Dada uma definição de enum como:
Podemos definir uma macro para converter um valor de enum para sua string correspondente, como mostrado abaixo.
A
switch
instrução usada no bloco é para verificação de tipo e também para obter o suporte de preenchimento automático no Xcode.fonte
Eu tinha um grande tipo enumerado que queria convertê-lo em uma
NSDictionary
pesquisa. Acabei usandosed
do terminal OSX como:que pode ser lido como: 'capture a primeira palavra na linha e produza @ (word): @ "word",'
Essa regex converte a enumeração em um arquivo de cabeçalho chamado 'ObservationType.h', que contém:
em algo como:
que pode ser agrupado em um método usando a sintaxe objetiva-c moderna
@{ }
(conforme explicado por @ yar1vn acima) para criar umaNSDictionary
pesquisa:A
dispatch_once
placa da caldeira é apenas para garantir que a variável estática seja inicializada de maneira segura para roscas.Nota: Achei a expressão sed regex no OSX estranha - quando tentei
+
combinar 'um ou mais', não funcionou e tive que usar{1,}
como substitutofonte
Eu uso uma variação na resposta de Barry Walk, que em ordem de importância:
POR EXEMPLO:
fonte
A @pixel adicionou a resposta mais brilhante aqui: https://stackoverflow.com/a/24255387/1364257 Por favor, vote nele novamente!
Ele usa a macro X pura da década de 1960. (Eu mudei um pouco o código dele para o ObjC moderno)
É isso aí. Limpo e arrumado. Graças a @pixel! https://stackoverflow.com/users/21804/pixel
fonte
Eu combinei várias abordagens aqui. Gosto da ideia do pré-processador e da lista indexada.
Não há alocação dinâmica extra e, devido ao alinhamento, o compilador pode otimizar a pesquisa.
fonte
Primeiro de tudo, com relação ao FormatType.JSON: JSON não é um membro do FormatType, é um valor possível do tipo. FormatType nem é um tipo composto - é um escalar.
Segundo, a única maneira de fazer isso é criar uma tabela de mapeamento. A maneira mais comum de fazer isso no Objective-C é criar uma série de constantes se referindo aos seus "símbolos", assim você teria
NSString *FormatTypeJSON = @"JSON"
e assim por diante.fonte
o seguinte fornece uma solução para que a adição de uma nova enum exija apenas uma edição em uma linha, trabalho semelhante ao de adicionar uma única linha em uma lista de enum {}.
fonte
Cada resposta aqui basicamente diz a mesma coisa, crie uma enum regular e use um getter personalizado para alternar entre as strings.
Emprego uma solução muito mais simples, mais rápida, mais curta e mais limpa - usando Macros!
Então você pode simplesmente começar a digitar
kNam...
e o preenchimento automático exibirá as listas que você deseja!Além disso, se você quiser manipular a lógica para todos os nomes de uma só vez, basta enumerar rapidamente a matriz literal na ordem, da seguinte maneira:
for (NSString *kName in kNames_allNames) {}
Por fim, a conversão do NSString nas macros garante um comportamento semelhante ao typedef!
Aproveitar!
fonte
Muitas respostas, todas razoavelmente boas.
Se você procura uma solução genérica, Objective C, que usa algumas macros ...
O principal recurso é que ele usa a enumeração como um índice em uma matriz estática de constantes NSString. a própria matriz é agrupada em uma função para torná-la mais parecida com o conjunto de funções NSStringFromXXX prevalecentes nas APIs da Apple.
você precisará
#import "NSStringFromEnum.h"
encontrar aqui http://pastebin.com/u83RR3Vk[EDIT] também precisa ser
#import "SW+Variadic.h"
encontrado aqui http://pastebin.com/UEqTzYLfExemplo 1: defina completamente um NEW enum typedef, com conversores de string.
em myfile.h
em myfile.m:
usar :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
retorna@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
retornachain_previous
Exemplo 2: fornecer rotinas de conversão para uma enum existente também demonstra o uso de uma sequência de configurações e renomeando o nome do tipo usado nas funções.
em myfile.h
em myfile.m:
fonte
Aqui está trabalhando -> https://github.com/ndpiparava/ObjcEnumString
fonte
Dependendo das suas necessidades, você também pode usar as diretivas do compilador para simular o comportamento que está procurando.
Lembre-se das deficiências usuais do compilador (não digite seguro, a cópia direta e a colagem aumentam o arquivo de origem)
fonte
#define
estiver visível, você não será capaz de usar o valor enum real (ou seja,JSON
será substituído com@"JSON"
pelo pré-processador e irá resultar em um erro do compilador ao atribuir a umFormatType
.