Angenommen, ich habe ein typedef in meiner .h-Datei als solches deklariert:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Ich möchte eine Funktion erstellen, die den numerischen Wert des typedef in eine Zeichenfolge konvertiert. Zum Beispiel, wenn die Nachricht [self toString:JSON]
gesendet wurde; es würde 'JSON' zurückgeben.
Die Funktion würde ungefähr so aussehen:
-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}
Übrigens, wenn ich diese Syntax versuche
[self toString:FormatType.JSON];
Um den typedef-Wert an die Methode zu übergeben, wird eine Fehlermeldung angezeigt. Was vermisse ich?
c
objective-c
enums
typedef
Craig
quelle
quelle
Antworten:
Dies ist wirklich eine C-Frage, die nicht spezifisch für Objective-C ist (eine Obermenge der C-Sprache). Aufzählungen in C werden als Ganzzahlen dargestellt. Sie müssen also eine Funktion schreiben, die eine Zeichenfolge mit einem Aufzählungswert zurückgibt. Es gibt viele Möglichkeiten, dies zu tun. Ein Array von Zeichenfolgen, so dass der Aufzählungswert als Index für das Array verwendet werden kann, oder eine Zuordnungsstruktur (z. B. eine
NSDictionary
), die einen Aufzählungswert einer Zeichenfolge zuordnet, funktioniert, aber ich finde, dass diese Ansätze nicht so klar sind wie eine Funktion, die macht die Konvertierung explizit (und den Array-Ansatz, obwohl der klassischeC
Weg gefährlich ist, wenn Ihre Enum-Werte nicht von 0 abweichen). So etwas würde funktionieren:Ihre verwandte Frage zur korrekten Syntax für einen Enum-Wert lautet, dass Sie nur den Wert (z. B.
JSON
) und nicht dieFormatType.JSON
Sytax verwenden.FormatType
ein Typ ist und die ENUM - Werte (zBJSON
,XML
usw.) sind Werte , die Sie zu diesem Typ zuordnen.quelle
Sie können es nicht einfach machen. In C und Objective-C sind Aufzählungen wirklich nur verherrlichte ganzzahlige Konstanten. Sie müssen selbst eine Namenstabelle erstellen (oder bei einem Präprozessor-Missbrauch). Beispielsweise:
Die Gefahr dieses Ansatzes besteht darin, dass Sie, wenn Sie jemals die Aufzählung ändern, daran denken müssen, das Array von Namen zu ändern. Sie können dieses Problem mit einem Missbrauch des Präprozessors lösen, aber es ist schwierig und hässlich.
Beachten Sie auch, dass dies voraussetzt, dass Sie eine gültige Aufzählungskonstante haben. Wenn Sie einen ganzzahligen Wert aus einer nicht vertrauenswürdigen Quelle haben, müssen Sie zusätzlich überprüfen, ob Ihre Konstante gültig ist, z. B. indem Sie einen Wert "past max" in Ihre Aufzählung aufnehmen oder prüfen, ob er kleiner als die Arraylänge ist
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
.quelle
string[] = { [XML] = "XML" }
um sicherzustellen, dass die Zeichenfolge ordnungsgemäß mit den Aufzählungen übereinstimmtFormatType_toString[]
Array durchlaufen und-isEqualToString:
jedes Element aufrufen , um eine Übereinstimmung zu finden, oder einen Zuordnungsdatentyp verwendenNSDictionary
, um beispielsweise die inverse Lookup-Zuordnung beizubehalten.FormatType_toString
Array zu vergessen .Meine Lösung:
Bearbeiten: Ich habe am Ende mit Modern Obj-C noch eine bessere Lösung hinzugefügt.
1. Fügen
Sie Namen als Schlüssel in ein Array ein.
Stellen Sie sicher, dass die Indizes die entsprechenden Aufzählungen und in der richtigen Reihenfolge sind (ansonsten Ausnahme).
Hinweis: names ist eine Eigenschaft, die als * _names * synthetisiert wird.
Code wurde nicht für die Kompilierung überprüft, aber ich habe die gleiche Technik in meiner App verwendet.
//
2.
Mit Modern Obj-C können Sie ein Wörterbuch verwenden, um Beschreibungen mit Schlüsseln in der Aufzählung zu verknüpfen.
Bestellung spielt keine Rolle .
Verwendung (in einer Klasseninstanzmethode):
quelle
+[typeDisplayNames]
, dass Sie das Wörterbuch bei jedem Anruf neu erstellen. Dies ist in Ordnung, wenn es nur einige Male aufgerufen wird, aber wenn es viele Male aufgerufen wird, wird dies sehr teuer. Eine bessere Lösung könnte darin bestehen, das Wörterbuch zu einem Singleton zu machen, sodass es nur einmal erstellt wird und ansonsten im Speicher bleibt. Klassisches Speicher-gegen-CPU-Rätsel.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
Kommentaren keine Zeilenumbrüche vornehmen. Tut mir leid.Ich schlage vor, die Antwort von @AdamRosenfield, den Kommentar von @Christoph und einen weiteren Trick zu kombinieren, um mit einfachen C-Aufzählungen umzugehen:
Im schlimmsten Fall - wenn Sie beispielsweise die Aufzählung ändern, aber vergessen, das Namensarray zu ändern - wird für diesen Schlüssel null zurückgegeben.
quelle
Definieren Sie typedef enum im Klassenheader:
Schreiben Sie eine solche Methode in der Klasse:
Haben Sie die Zeichenfolgen in der Datei Localizable.strings :
quelle
Ich würde das # String-Token des Compilers verwenden (zusammen mit Makros, um alles kompakter zu machen):
quelle
Ich mag die
#define
Art und Weise, dies zu tun:// Platziere dies in deiner .h-Datei außerhalb des @ interface-Blocks
Quelle(Quelle nicht mehr verfügbar)quelle
nil
wennarray.count <= enumValue
?Ich habe eine Art Mix aus allen auf dieser Seite gefundenen Lösungen erstellt, um meine zu erstellen. Es ist eine Art objektorientierte Enumerweiterung oder so.
Wenn Sie mehr als nur Konstanten (dh ganze Zahlen) benötigen, benötigen Sie wahrscheinlich ein Modellobjekt (wir sprechen alle über MVC, oder?)
Stellen Sie sich einfach die Frage, bevor Sie diese verwenden. Habe ich Recht? Benötigen Sie nicht tatsächlich ein echtes Modellobjekt, das von einem Webservice, einer Plist, einer SQLite-Datenbank oder CoreData initialisiert wurde?
Wie auch immer, hier kommt der Code (MPI ist für "My Project Initials", jeder verwendet diesen oder seinen Namen, wie es scheint):
MyWonderfulType.h
::Und
MyWonderfulType.m
:quelle
Eine andere Lösung:
In Ihrer Methode können Sie verwenden:
quelle
Verbesserte @ yar1vn-Antwort durch Löschen der Zeichenfolgenabhängigkeit:
Wenn Sie also den Namen des Enum-Eintrags ändern, wird die entsprechende Zeichenfolge geändert. Nützlich für den Fall, dass Sie dem Benutzer diese Zeichenfolge nicht anzeigen möchten.
quelle
"foo""bar"
, wird die Zeichenfolge"foobar"
beim Kompilieren angezeigt. Also#define VariableName(arg) (@""#arg)
wird sich erweiternVariableName(MyEnum)
zu sein(@"""MyEnum")
. Das führt zur Zeichenfolge@"MyEnum"
.Gegeben eine Aufzählungsdefinition wie:
Wir können ein Makro definieren, um einen Aufzählungswert in die entsprechende Zeichenfolge zu konvertieren, wie unten gezeigt.
Die
switch
im Block verwendete Anweisung dient zur Typprüfung und zur Unterstützung der automatischen Vervollständigung in Xcode.quelle
Ich hatte einen großen Aufzählungstyp, den ich in eine
NSDictionary
Suche konvertieren wollte . Am Ende habe ichsed
vom OSX-Terminal Folgendes verwendet:Dies kann wie folgt gelesen werden: 'Erfassen Sie das erste Wort in der Zeile und geben Sie @ (Wort): @ "Wort" aus.'
Dieser reguläre Ausdruck konvertiert die Aufzählung in eine Header-Datei mit dem Namen 'ObservationType.h', die Folgendes enthält:
in so etwas wie:
@{ }
Diese kann dann mithilfe der modernen Objective-C-Syntax (wie oben durch @ yar1vn erläutert) in eine Methode eingeschlossen werden , um eineNSDictionary
Suche zu erstellen :Die
dispatch_once
Kesselplatte soll lediglich sicherstellen, dass die statische Variable gewindesicher initialisiert wird.Hinweis: Ich fand den sed regex-Ausdruck unter OSX seltsam - als ich versuchte, ihn
+
mit "einem oder mehreren" abzugleichen, funktionierte er nicht und musste ihn{1,}
als Ersatz verwendenquelle
Ich verwende eine Variation der Antwort von Barry Walk, die in der Reihenfolge ihrer Wichtigkeit lautet:
Z.B:
quelle
@pixel hat hier die brillanteste Antwort hinzugefügt: https://stackoverflow.com/a/24255387/1364257 Bitte, stimmen Sie ihn ab!
Er benutzt das nette X-Makro aus den 1960ern. (Ich habe seinen Code für das moderne ObjC ein wenig geändert)
Das ist es. Sauber und ordentlich. Danke an @pixel! https://stackoverflow.com/users/21804/pixel
quelle
Ich habe hier mehrere Ansätze kombiniert. Ich mag die Idee des Präprozessors und der indizierten Liste.
Es gibt keine zusätzliche dynamische Zuordnung, und aufgrund des Inlinings kann der Compiler möglicherweise die Suche optimieren.
quelle
Zunächst in Bezug auf FormatType.JSON: JSON ist kein Mitglied von FormatType, sondern ein möglicher Wert des Typs. FormatType ist nicht einmal ein zusammengesetzter Typ - es ist ein Skalar.
Zweitens besteht die einzige Möglichkeit darin, eine Zuordnungstabelle zu erstellen. Der üblichere Weg, dies in Objective-C zu tun, besteht darin, eine Reihe von Konstanten zu erstellen, die sich auf Ihre "Symbole" beziehen
NSString *FormatTypeJSON = @"JSON"
und so weiter.quelle
Im Folgenden finden Sie eine Lösung, bei der zum Hinzufügen einer neuen Aufzählung nur eine einzeilige Bearbeitung erforderlich ist. Dies ähnelt dem Hinzufügen einer einzelnen Zeile in einer Aufzählungsliste {}.
quelle
Jede Antwort hier sagt im Grunde dasselbe, erstellt eine reguläre Aufzählung und verwendet dann einen benutzerdefinierten Getter, um zwischen Zeichenfolgen zu wechseln.
Ich verwende eine viel einfachere Lösung, die schneller, kürzer und sauberer ist - mit Makros!
Dann können Sie einfach mit der Eingabe beginnen
kNam...
Eingabe und die automatische Vervollständigung zeigt die gewünschten Listen an!Wenn Sie die Logik für alle Namen gleichzeitig verarbeiten möchten, können Sie das Literal-Array einfach wie folgt schnell auflisten:
for (NSString *kName in kNames_allNames) {}
Schließlich sorgt das NSString-Casting in den Makros für ein ähnliches Verhalten wie typedef!
Genießen!
quelle
Viele Antworten sind alle ziemlich gut.
Wenn Sie nach einer generischen Objective C-Lösung suchen, die einige Makros verwendet ...
Das Hauptmerkmal ist, dass die Aufzählung als Index für ein statisches Array von NSString-Konstanten verwendet wird. Das Array selbst ist in eine Funktion eingebunden, um es der in den Apple-APIs vorherrschenden Suite von NSStringFromXXX-Funktionen ähnlicher zu machen.
Sie müssen
#import "NSStringFromEnum.h"
hier http://pastebin.com/u83RR3Vk finden[EDIT] muss
#import "SW+Variadic.h"
auch hier gefunden werden http://pastebin.com/UEqTzYLfBeispiel 1: Definieren Sie eine NEUE Aufzählung typedef mit Zeichenfolgenkonvertern vollständig.
in myfile.h
in myfile.m:
benutzen :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
kehrt zurück@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
kehrt zurückchain_previous
Beispiel 2: Das Bereitstellen von Konvertierungsroutinen für eine vorhandene Aufzählung zeigt auch die Verwendung einer Einstellungszeichenfolge und das Umbenennen des in den Funktionen verwendeten Typnamens.
in myfile.h
in myfile.m:
quelle
Hier funktioniert -> https://github.com/ndpiparava/ObjcEnumString
quelle
Abhängig von Ihren Anforderungen können Sie alternativ Compiler-Anweisungen verwenden, um das gesuchte Verhalten zu simulieren.
Denken Sie nur an die üblichen Mängel des Compilers (nicht typsicher, direktes Kopieren und Einfügen vergrößert die Quelldatei)
quelle
#define
sichtbar ist, können Sie den tatsächlichen Aufzählungswert nicht verwenden (dh erJSON
wird@"JSON"
durch den Präprozessor ersetzt und führt zu einem Compilerfehler bei der Zuweisung zu einemFormatType
.