Zakładając, że mam deklarację typedef w swoim pliku .h jako taką:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Chciałbym zbudować funkcję, która konwertuje wartość liczbową typu typedef na ciąg. Na przykład, jeśli wiadomość [self toString:JSON]
została wysłana; zwróci „JSON”.
Funkcja wyglądałaby mniej więcej tak:
-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}
Nawiasem mówiąc, jeśli spróbuję tej składni
[self toString:FormatType.JSON];
aby przekazać wartość typedef do metody, pojawia się błąd. czego mi brakuje?
c
objective-c
enums
typedef
Craig
źródło
źródło
Odpowiedzi:
To jest naprawdę pytanie C, nie specyficzne dla Objective-C (który jest nadzbiorem języka C). Wyliczenia w C są przedstawiane jako liczby całkowite. Musisz więc napisać funkcję, która zwraca ciąg znaków o wartości wyliczenia. Istnieje wiele sposobów, aby to zrobić. Tablica ciągów, taka że wartość wyliczenia może być używana jako indeks tablicy lub struktury mapy (np.
NSDictionary
), Która mapuje wartość wyliczenia na ciąg znaków, ale uważam, że te podejścia nie są tak jasne, jak funkcja, która sprawia, że konwersja jest jawna (i podejście tablicowe, chociaż klasycznyC
sposób jest niebezpieczny, jeśli wartości wyliczenia nie są ciągłe od 0). Coś takiego zadziałałoby:Twoje pokrewne pytanie dotyczące prawidłowej składni wartości wyliczenia dotyczy tego, że używasz tylko wartości (np.
JSON
), A nieFormatType.JSON
sytax.FormatType
Jest to rodzaj i wartości enum (npJSON
,XML
etc.) są wartościami, które można przypisać do danego typu.źródło
Nie możesz tego łatwo zrobić. W C i Objective-C wyliczenia są w rzeczywistości gloryfikowanymi stałymi całkowitymi. Będziesz musiał samodzielnie wygenerować tabelę nazw (lub z pewnym nadużyciem preprocesora). Na przykład:
Niebezpieczeństwo tego podejścia polega na tym, że jeśli kiedykolwiek zmienisz wyliczenie, musisz pamiętać o zmianie tablicy nazw. Możesz rozwiązać ten problem, używając pewnego nadużycia preprocesora, ale jest to trudne i brzydkie.
Zauważ również, że przy założeniu, że masz prawidłową stałą wyliczenia. Jeśli wartość całkowitą z niezaufanych źródeł, dodatkowo trzeba zrobić czek, że stała jest ważny, na przykład przez wprowadzenie „przeszłość max” wartość w swojej wyliczenia, lub sprawdzając, czy jest to mniej niż długość tablicy,
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
.źródło
string[] = { [XML] = "XML" }
aby upewnić się, że ciąg pasuje do wyliczeńFormatType_toString[]
tablicę i wywołać-isEqualToString:
każdy element, aby znaleźć dopasowanie, albo użyć typu danych mapowania, takiego jakNSDictionary
utrzymywanie odwrotnej mapy wyszukiwania.FormatType_toString
tablicy.Moje rozwiązanie:
edycja: na końcu dodałem jeszcze lepsze rozwiązanie, używając nowoczesnego Obj-C
1.
Umieść nazwy jako klucze w tablicy.
Upewnij się, że indeksy są odpowiednimi wyliczeniami i we właściwej kolejności (w przeciwnym razie wyjątek).
uwaga: nazwy to właściwość syntetyzowana jako * _names *;
kod nie został sprawdzony pod kątem kompilacji, ale użyłem tej samej techniki w mojej aplikacji.
//
2.
Używając nowoczesnego Obj-C możemy użyć słownika do powiązania opisów z kluczami w wyliczeniu.
Zamówienie NIE MA znaczenia .
Użycie (w metodzie instancji klasy):
źródło
+[typeDisplayNames]
, ponownie tworzysz słownik. Jest to w porządku, jeśli dzwoni się tylko kilka razy, ale jeśli dzwoni się wiele razy, będzie to bardzo kosztowne. Lepszym rozwiązaniem może być uczynienie ze słownika singletonu, więc jest on tworzony tylko raz iw innym przypadku pozostaje w pamięci. Klasyczna pamięć a zagadka procesora.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
Komentarze nie pozwolą ci na łamanie linii, przepraszam za to.Łącząc odpowiedź @AdamRosenfield, komentarz @Christoph i inną sztuczkę do obsługi zwykłych wyliczeń C, które sugeruję:
W najgorszym przypadku - na przykład, jeśli zmienisz wyliczenie, ale zapomnisz zmienić tablicę nazw - zwróci to nil dla tego klucza.
źródło
zdefiniuj typedef enum w nagłówku klasy:
napisz taką metodę w klasie:
mają ciągi znaków w pliku Localizable.strings :
źródło
Użyłbym tokena ciągu # kompilatora (wraz z makrami, aby uczynić go bardziej kompaktowym):
źródło
Podoba mi się
#define
sposób robienia tego:// Umieść to w swoim pliku .h, poza blokiem @interface
źródło(źródło nie jest już dostępne)źródło
nil
jeśliarray.count <= enumValue
?Zrobiłem coś w rodzaju mieszanki wszystkich rozwiązań znalezionych na tej stronie, aby stworzyć moje, jest to rodzaj zorientowanego obiektowo rozszerzenia wyliczenia lub coś w tym rodzaju.
W rzeczywistości, jeśli potrzebujesz czegoś więcej niż tylko stałych (tj. Liczb całkowitych), prawdopodobnie potrzebujesz obiektu modelu (wszyscy mówimy o MVC, prawda?)
Po prostu zadaj sobie pytanie przed użyciem tego, czy mam rację, czy w rzeczywistości nie potrzebujesz prawdziwego obiektu modelu, zainicjowanego z usługi sieciowej, plist, bazy danych SQLite lub CoreData?
W każdym razie tutaj jest kod (MPI oznacza „Moje inicjały projektu”, wszyscy używają tego lub ich nazwy):
MyWonderfulType.h
:Oraz
MyWonderfulType.m
:źródło
Inne rozwiązanie:
W swojej metodzie możesz użyć:
źródło
Ulepszona odpowiedź @ yar1vn przez usunięcie zależności od ciągu:
Tak więc, kiedy zmienisz nazwę wpisu wyliczenia, odpowiedni ciąg zostanie zmieniony. Przydatne w przypadku, gdy nie zamierzasz wyświetlać tego ciągu użytkownikowi.
źródło
"foo""bar"
,"foobar"
po kompilacji powstaje ciąg . Tak,#define VariableName(arg) (@""#arg)
będzie rozwijaćVariableName(MyEnum)
się(@"""MyEnum")
. Spowoduje to powstanie ciągu@"MyEnum"
.Biorąc pod uwagę definicję wyliczenia, taką jak:
Możemy zdefiniować makro, aby przekonwertować wartość wyliczenia na odpowiadający jej ciąg, jak pokazano poniżej.
switch
Wykorzystywane w bloku stwierdzenie jest dla typu kontroli, a także uzyskać autouzupełniania wsparcie w Xcode.źródło
Miałem duży wyliczony typ i chciałem przekształcić go w
NSDictionary
wyszukiwanie. Skończyło się na używaniused
z terminala OSX jako:które można odczytać jako: 'przechwyć pierwsze słowo w wierszu i wypisz @ (słowo): @ "słowo",'
To wyrażenie regularne konwertuje wyliczenie w pliku nagłówkowym o nazwie „ObservationType.h”, który zawiera:
na coś takiego:
które można następnie
@{ }
opakować w metodę używającą nowoczesnej składni obiektywnej-c (jak wyjaśniono powyżej w @ yar1vn), aby utworzyćNSDictionary
odnośnik:Plik
dispatch_once
kotłowa służy tylko do zapewnienia inicjalizacji zmiennej statycznej w sposób bezpieczny dla wątków.Uwaga: stwierdziłem, że wyrażenie wyrażenia regularnego sed na OSX jest dziwne - kiedy próbowałem użyć
+
dopasowania `` jednego lub więcej '', nie działało i musiałem uciekać się do użycia{1,}
jako zamiennikaźródło
Używam wariacji na temat odpowiedzi Barry'ego Walk'a, w kolejności od najważniejszej:
NA PRZYKŁAD:
źródło
@pixel dodał tutaj najbardziej genialną odpowiedź: https://stackoverflow.com/a/24255387/1364257 Proszę, zagłosuj na niego!
Używa zgrabnego makra X z lat 60-tych. (Zmieniłem nieco jego kod dla nowoczesnego ObjC)
Otóż to. Czysto i schludnie. Dzięki @pixel! https://stackoverflow.com/users/21804/pixel
źródło
Połączyłem tutaj kilka podejść. Podoba mi się pomysł preprocesora i zindeksowanej listy.
Nie ma dodatkowej alokacji dynamicznej, a ze względu na wbudowanie kompilator może być w stanie zoptymalizować wyszukiwanie.
źródło
Po pierwsze, w odniesieniu do FormatType.JSON: JSON nie jest członkiem FormatType, jest to możliwa wartość typu. FormatType nie jest nawet typem złożonym - to skalar.
Po drugie, jedynym sposobem na to jest utworzenie tabeli mapowania. Bardziej powszechnym sposobem na zrobienie tego w Objective-C jest utworzenie serii stałych odnoszących się do twoich „symboli”, tak abyś miał
NSString *FormatTypeJSON = @"JSON"
i tak dalej.źródło
Poniżej przedstawiono rozwiązanie polegające na tym, że dodanie nowego wyliczenia wymaga tylko edycji w jednym wierszu, podobnej pracy do dodawania pojedynczego wiersza na liście wyliczeń {}.
źródło
Każda odpowiedź tutaj w zasadzie mówi to samo, utwórz zwykłe wyliczenie, a następnie użyj niestandardowego narzędzia pobierającego, aby przełączać się między ciągami.
Używam znacznie prostszego rozwiązania, które jest szybsze, krótsze i czystsze - używając makr!
Następnie możesz po prostu zacząć pisać
kNam...
a autouzupełnianie wyświetli żądane listy!Dodatkowo, jeśli chcesz obsłużyć logikę dla wszystkich nazw naraz, możesz po prostu szybko wyliczyć tablicę literałów w kolejności, w następujący sposób:
for (NSString *kName in kNames_allNames) {}
Na koniec rzutowanie NSString w makrach zapewnia zachowanie podobne do typedef!
Cieszyć się!
źródło
Wiele odpowiedzi jest całkiem dobrych.
Jeśli szukasz ogólnego rozwiązania Objective C, które wykorzystuje niektóre makra ...
Kluczową cechą jest to, że używa wyliczenia jako indeksu do statycznej tablicy stałych NSString. sama tablica jest opakowana w funkcję, aby bardziej przypominała zestaw funkcji NSStringFromXXX rozpowszechnionych w interfejsach API Apple.
musisz
#import "NSStringFromEnum.h"
znaleźć tutaj http://pastebin.com/u83RR3Vk[EDYCJA] również wymaga
#import "SW+Variadic.h"
znalezienia tutaj http://pastebin.com/UEqTzYLfPrzykład 1: całkowicie zdefiniuj NOWY typ wyliczenia z konwerterami ciągów.
w myfile.h
w myfile.m:
używać :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
zwroty@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
zwrotychain_previous
Przykład 2: dostarczanie procedur konwersji dla istniejącego wyliczenia demonstruje również użycie ciągu ustawień i zmianę nazwy nazwy typu używanej w funkcjach.
w myfile.h
w myfile.m:
źródło
Tutaj działa -> https://github.com/ndpiparava/ObjcEnumString
źródło
W zależności od potrzeb możesz alternatywnie użyć dyrektyw kompilatora, aby zasymulować zachowanie, którego szukasz.
Pamiętaj tylko o typowych wadach kompilatora (nie wpisuj bezpiecznego, bezpośrednie kopiowanie i wklejanie zwiększa rozmiar pliku źródłowego)
źródło
#define
jest widoczne, nie będzie można użyć rzeczywistej wartości wyliczenia (tj.JSON
zostanie zastąpiona@"JSON"
przez preprocesor i spowoduje błąd kompilatora podczas przypisywania do aFormatType
.