Konvertieren Sie object-c typedef in sein String-Äquivalent
Lesezeit: 7 Minuten
Craig
Angenommen, ich habe eine Typedef in meiner .h-Datei als solche deklariert:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Ich möchte eine Funktion bauen, die den numerischen Wert des Typedef in einen String umwandelt. Wenn zum Beispiel die Nachricht [self toString:JSON] wurde gesendet; es würde ‘JSON’ zurückgeben.
Die Funktion würde in etwa 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, erhalte ich eine Fehlermeldung. Was vermisse ich?
Siehe meine Antwort unter stackoverflow.com/questions/6331762/enum-values-to-nsstring-ios für eine sauberere Lösung des Problems.
– BooTooMany
22. Oktober 2014 um 20:52 Uhr
Vielleicht sollten wir eine Umarmung geben Schnell Sprache auf Aufzählung.
Für eine Lösung, ohne einfach einen benutzerdefinierten Getter für Enum zu verwenden, der in einen String konvertiert, sehen Sie sich das String-Cast-Makro-Array an: stackoverflow.com/a/53755377/2057171
– Albert Renshaw
13. Dezember 2018 um 5:23 Uhr
Barry Wark
Dies ist wirklich eine C-Frage, nicht spezifisch für Objective-C (das eine Obermenge der C-Sprache ist). Aufzählungen in C werden als ganze Zahlen dargestellt. Sie müssen also eine Funktion schreiben, die einen String mit einem Enum-Wert zurückgibt. Es gibt viele Möglichkeiten, dies zu tun. Ein Array von Strings, sodass der Enum-Wert als Index in das Array oder eine Map-Struktur (z. B. eine NSDictionary), die einen Enum-Wert einem String zuordnet, funktionieren, aber ich finde, dass diese Ansätze nicht so klar sind wie eine Funktion, die die Konvertierung explizit macht (und der Array-Ansatz, obwohl der klassische C Weg ist gefährlich, wenn Ihre Enum-Werte nicht fortlaufend von 0 sind). So etwas würde funktionieren:
- (NSString*)formatTypeToString:(FormatType)formatType {
NSString *result = nil;
switch(formatType) {
case JSON:
result = @"JSON";
break;
case XML:
result = @"XML";
break;
case Atom:
result = @"Atom";
break;
case RSS:
result = @"RSS";
break;
default:
[NSException raise:NSGenericException format:@"Unexpected FormatType."];
}
return result;
}
Ihre verwandte Frage zur korrekten Syntax für einen Aufzählungswert ist, dass Sie nur den Wert verwenden (z JSON), nicht der FormatType.JSON Syntax. FormatType ein Typ ist und die Aufzählungswerte (zB JSON, XMLusw.) sind Werte, die Sie diesem Typ zuweisen können.
Adam Rosenfeld
Sie können es nicht einfach tun. In C und Objective-C sind Aufzählungen wirklich nur verherrlichte ganzzahlige Konstanten. Sie müssen selbst (oder mit etwas Vorprozessormissbrauch) eine Tabelle mit Namen erstellen. Zum Beispiel:
// In a header file
typedef enum FormatType {
JSON,
XML,
Atom,
RSS
} FormatType;
extern NSString * const FormatType_toString[];
// In a source file
// initialize arrays with explicit indices to make sure
// the string match the enums properly
NSString * const FormatType_toString[] = {
[JSON] = @"JSON",
[XML] = @"XML",
[Atom] = @"Atom",
[RSS] = @"RSS"
};
...
// To convert enum to string:
NSString *str = FormatType_toString[theEnumValue];
Die Gefahr bei diesem Ansatz besteht darin, dass Sie, wenn Sie jemals die Aufzählung ändern, daran denken müssen, das Array der Namen zu ändern. Sie können dieses Problem mit etwas Präprozessormissbrauch lösen, aber es ist knifflig und hässlich.
Beachten Sie auch, dass dies davon ausgeht, 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. sizeof(FormatType_toString) / sizeof(FormatType_toString[0]).
Sie können Arrays mit expliziten Indizes initialisieren, z string[] = { [XML] = "XML" } um sicherzustellen, dass die Zeichenfolge richtig mit den Aufzählungen übereinstimmt
– Christoph
7. Juli 2009 um 23:39 Uhr
@Christoph: Ja, das ist ein C99-Feature namens ausgewiesene Initialisierer. Das ist gut für die Verwendung in Objective-C (das auf C99 basiert), aber für generischen C89-Code können Sie diese nicht verwenden.
– Adam Rosenfield
3. September 2013 um 17:55 Uhr
Gibt es eine Möglichkeit, in die andere Richtung zu gehen? Zum Beispiel die Aufzählung bei einer Zeichenfolge zurückerhalten?
– Jameo
17. Februar 2014 um 16:44 Uhr
@Jameo: Ja, aber es ist nicht ganz so einfach wie eine Array-Suche durchzuführen. Sie müssen entweder durch die iterieren FormatType_toString[] Array und Aufruf -isEqualToString: für jedes Element, um eine Übereinstimmung zu finden, oder verwenden Sie einen Mapping-Datentyp wie z NSDictionary um die inverse Nachschlagekarte beizubehalten.
– Adam Rosenfield
17. Februar 2014 um 16:55 Uhr
Der Trick von Max O ist gut, um zu vergessen, Einträge in der hinzuzufügen FormatType_toString Reihe.
– AechoLiu
15. Dezember 2015 um 2:47 Uhr
Jariv Nissim
Meine Lösung:
Bearbeiten: Ich habe am Ende noch eine bessere Lösung hinzugefügt, mit Modern Obj-C
1. Geben Sie Namen als Schlüssel in ein Array ein.
Stellen Sie sicher, dass die Indizes die entsprechenden Aufzählungen sind, und in der richtigen reihenfolge (sonst Ausnahme).
Hinweis: Namen ist eine als *_names* synthetisierte Eigenschaft;
Code wurde nicht auf Kompilierung geprü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. Die Reihenfolge spielt keine Rolle.
Beachten Sie das bei jedem Anruf +[typeDisplayNames], erstellen Sie das Wörterbuch neu. Das ist in Ordnung, wenn es nur ein paar Mal aufgerufen wird, aber wenn es viele Male aufgerufen wird, wird es 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-vs.-CPU-Rätsel.
– Joel Fischer
11. April 2014 um 14:24 Uhr
Oder ändern Sie es in eine statische Variable, z static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict; Kommentare lassen keinen Zeilenumbruch zu, tut mir leid.
– Natanavra
29. Juni 2017 um 14:44 Uhr
Ich schlage vor, die Antwort von @AdamRosenfield, den Kommentar von @Christoph und einen weiteren Trick zum Umgang mit einfachen C-Enumerationen zu kombinieren:
// In a header file
typedef enum {
JSON = 0, // explicitly indicate starting index
XML,
Atom,
RSS,
FormatTypeCount, // keep track of the enum size automatically
} FormatType;
extern NSString *const FormatTypeName[FormatTypeCount];
// In a source file
NSString *const FormatTypeName[FormatTypeCount] = {
[JSON] = @"JSON",
[XML] = @"XML",
[Atom] = @"Atom",
[RSS] = @"RSS",
};
// Usage
NSLog(@"%@", FormatTypeName[XML]);
Im schlimmsten Fall – wie wenn Sie die Aufzählung ändern, aber vergessen, das Namens-Array zu ändern – wird für diesen Schlüssel null zurückgegeben.
@Daij-Djan, was ist mit der Rückkehr nil wenn array.count <= enumValue?
– anneblue
14. März 2014 um 10:13 Uhr
@anneblue, das würde den Fehler abfangen. Es wäre immer noch zerbrechlich, denn wenn Sie einen Aufzählungswert hinzufügen ODER sich der ganzzahlige Wert eines Aufzählungswerts ändert, geht dies schief. Die akzeptierte Antwort wäre gut
– Daij-Djan
14. März 2014 um 12:18 Uhr
@codercat 🙁 Entschuldigung – ich bin mir nicht sicher, was mit dieser Website passiert ist. Nicht auf dem Weg zurück, wenn die Maschine auch …
– Lindon Fuchs
20. Mai 2014 um 7:06 Uhr
Ich habe eine kleine Frage zu obiger Antwort. So konvertieren Sie ein Zeichenfolgenelement in kImageType. Ich muss die imageTypeEnumToString-Methode aufrufen, indem ich die Zeichenfolge übergebe. Können Sie mir bitte bei meinem Problem helfen?
– Ganesh
6. Oktober 2014 um 12:27 Uhr
Diese Antwort gefällt mir am besten, weil Sie die Zeichenfolgendefinitionen direkt neben den Aufzählungen haben. Geringste Chance, einen Wert zu verpassen. Und @Ganesh könnte Folgendes tun, um den Rohwert zu konvertieren: return (kImageType)[imageTypeArray indexOfObject:rawValue];
– Elia
4. Januar 2015 um 7:38 Uhr
14241100cookie-checkKonvertieren Sie object-c typedef in sein String-Äquivalentyes
Siehe meine Antwort unter stackoverflow.com/questions/6331762/enum-values-to-nsstring-ios für eine sauberere Lösung des Problems.
– BooTooMany
22. Oktober 2014 um 20:52 Uhr
Vielleicht sollten wir eine Umarmung geben Schnell Sprache auf Aufzählung.
– Itachi
26. August 2016 um 9:33 Uhr
@craig: hier ist die Lösung github.com/ndpiparava/ObjcEnumString
– Nitin
5. März 2017 um 17:07 Uhr
Für eine Lösung, ohne einfach einen benutzerdefinierten Getter für Enum zu verwenden, der in einen String konvertiert, sehen Sie sich das String-Cast-Makro-Array an: stackoverflow.com/a/53755377/2057171
– Albert Renshaw
13. Dezember 2018 um 5:23 Uhr