Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 332 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Convert objective-c typedef to its string equivalent

#1
Assuming that I have a typedef declared in my .h file as such:

typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;

I would like to build a function that converts the numeric value of the typedef to a string. For example, if the message `[self toString:JSON]` was sent; it would return 'JSON'.

The function would look something like this:

-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}

Incidentally, if I try this syntax

[self toString:FormatType.JSON];

to pass the typedef value to the method, I get an error. What am I missing?
Reply

#2
First of all, with regards to FormatType.JSON: JSON is not a member of FormatType, it's a possible value of the type. FormatType isn't even a composite type — it's a scalar.

Second, the only way to do this is to create a mapping table. The more common way to do this in Objective-C is to create a series of constants referring to your "symbols", so you'd have `NSString *FormatTypeJSON = @"JSON"` and so on.
Reply

#3
Depending on your needs, you could alternatively use compiler directives to simulate the behaviour you are looking for.

#define JSON @"JSON"
#define XML @"XML"
#define Atom @"Atom"
#define RSS @"RSS"

Just remember the usual compiler shortcomings, (not type safe, direct copy-paste makes source file larger)
Reply

#4
define typedef enum in class header:

typedef enum {
IngredientType_text = 0,
IngredientType_audio = 1,
IngredientType_video = 2,
IngredientType_image = 3
} IngredientType;

write a method like this in class:

+ (NSString*)typeStringForType:(IngredientType)_type {
NSString *key = [NSString stringWithFormat:@"IngredientType_%i", _type];
return NSLocalizedString(key, nil);
}

have the strings inside **Localizable.strings** file:

/* IngredientType_text */
"IngredientType_0" = "Text";
/* IngredientType_audio */
"IngredientType_1" = "Audio";
/* IngredientType_video */
"IngredientType_2" = "Video";
/* IngredientType_image */
"IngredientType_3" = "Image";

Reply

#5
Combining @AdamRosenfield answer, @Christoph comment and another trick to handle plain C enums I suggest:

// 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]);

In the worst case - like if you change the enum but forget to change the names array - it will return nil for this key.
Reply

#6
This is really a C question, not specific to Objective-C (which is a superset of the C language). Enums in C are represented as integers. So you need to write a function that returns a string given an enum value. There are many ways to do this. An array of strings such that the enum value can be used as an index into the array or a map structure (e.g. an `NSDictionary`) that maps an enum value to a string work, but I find that these approaches are not as clear as a function that makes the conversion explicit (and the array approach, although the classic `C` way is dangerous if your enum values are not continguous from 0). Something like this would work:

- (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;
}


Your related question about the correct syntax for an enum value is that you use just the value (e.g. `JSON`), not the `FormatType.JSON` sytax. `FormatType` is a type and the enum values (e.g. `JSON`, `XML`, etc.) are values that you can assign to that type.
Reply

#7
My solution: <BR>
<BR>
**edit: I've added even a better solution at the end, using Modern Obj-C**
<BR><BR>
1.<BR>Put names as keys in an array. <BR>
Make sure the indexes are the appropriate enums, **and in the right order** (otherwise exception). <BR>
note: *names* is a property synthesized as *_names*;

code was not checked for compilation, but I used the same technique in my app.

typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;

+ (NSArray *)names
{
static NSMutableArray * _names = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_names = [NSMutableArray arrayWithCapacity:4];
[_names insertObject:@"JSON" atIndex:JSON];
[_names insertObject:@"XML" atIndex:XML];
[_names insertObject:@"Atom" atIndex:Atom];
[_names insertObject:@"RSS" atIndex:RSS];
});

return _names;
}

+ (NSString *)nameForType:(FormatType)type
{
return [[self names] objectAtIndex:type];
}

<BR>//<BR><BR>
2.<BR>Using Modern Obj-C you we can use a dictionary to tie descriptions to keys in the enum.<BR>**Order DOES NOT matter**.
<BR><BR>

typedef NS_ENUM(NSUInteger, UserType) {
UserTypeParent = 0,
UserTypeStudent = 1,
UserTypeTutor = 2,
UserTypeUnknown = NSUIntegerMax
};

@property (nonatomic) UserType type;

+ (NSDictionary *)typeDisplayNames
{
return @{@(UserTypeParent) : @"Parent",
@(UserTypeStudent) : @"Student",
@(UserTypeTutor) : @"Tutor",
@(UserTypeUnknown) : @"Unknown"};
}

- (NSString *)typeDisplayName
{
return [[self class] typeDisplayNames][@(self.type)];
}

<BR>Usage (in a class instance method):<BR><BR>

NSLog(@"%@", [self typeDisplayName]);
<BR>
Reply

#8
I had a large enumerated type I wanted to convert it into an `NSDictionary` lookup. I ended up using `sed` from OSX terminal as:

$ sed -E 's/^[[:space:]]{1,}([[:alnum:]]{1,}).*$/ @(\1) : @"\1",/g' ObservationType.h

which can be read as: 'capture the first word on the line and output @(word) : @"word",'

This regex converts the enum in a header file named 'ObservationType.h' which contains:

typedef enum : int {
ObservationTypePulse = 1,
ObservationTypeRespRate = 2,
ObservationTypeTemperature = 3,
.
.
}

into something like:

@(ObservationTypePulse) : @"ObservationTypePulse",
@(ObservationTypeRespRate) : @"ObservationTypeRespRate",
@(ObservationTypeTemperature) : @"ObservationTypeTemperature",
.
.

which can then be wrapped in a method using modern objective-c syntax `@{ }` (as explained by @yar1vn above) to create a `NSDictionary` lookup :

-(NSDictionary *)observationDictionary
{
static NSDictionary *observationDictionary;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
observationDictionary = [[NSDictionary alloc] initWithDictionary:@{
@(ObservationTypePulse) : @"ObservationTypePulse",
@(ObservationTypeRespRate) : @"ObservationTypeRespRate",
.
.
}];
});
return observationDictionary;
}

The `dispatch_once` boiler-plate is just to ensure that the static variable is initialised in a thread-safe manner.

Note: I found the sed regex expression on OSX odd - when I tried to use `+` to match 'one or more' it didn't work and had to resort to using `{1,}` as a replacement
Reply

#9
I would use the compiler's # string token (along with macros to make it all more compact):

#define ENUM_START \
NSString* ret; \
switch(value) {

#define ENUM_CASE(evalue) \
case evalue: \
ret = @#evalue; \
break;

#define ENUM_END \
} \
return ret;

NSString*
_CvtCBCentralManagerStateToString(CBCentralManagerState value)
{
ENUM_START
ENUM_CASE(CBCentralManagerStateUnknown)
ENUM_CASE(CBCentralManagerStateResetting)
ENUM_CASE(CBCentralManagerStateUnsupported)
ENUM_CASE(CBCentralManagerStateUnauthorized)
ENUM_CASE(CBCentralManagerStatePoweredOff)
ENUM_CASE(CBCentralManagerStatePoweredOn)
ENUM_END
}

Reply

#10
Many answers all fairly good.

If you are after a generic, Objective C solution that uses some macros...

Key feature is it uses the enum as an index into a static array of NSString constants.
the array itself is wrapped into a function to make it more like the suite of NSStringFromXXX functions prevalent in the Apple APIs.

you will need to `#import "NSStringFromEnum.h"` found here

[To see links please register here]


[EDIT]
also needs `#import "SW+Variadic.h"` found here

[To see links please register here]


Example 1 : completely define a NEW enum typedef, with string converters.


in myfile.h
--------------------------------------------------------

#import "NSStringFromEnum.h"

#define define_Dispatch_chain_cmd(enum)\
enum(chain_done,=0)\
enum(chain_entry)\
enum(chain_bg)\
enum(chain_mt)\
enum(chain_alt)\
enum(chain_for_c)\
enum(chain_while)\
enum(chain_continue_for)\
enum(chain_continue_while)\
enum(chain_break_for)\
enum(chain_break_while)\
enum(chain_previous)\
enum(chain_if)\
enum(chain_else)\


interface_NSString_Enum_DefinitionAndConverters(Dispatch_chain_cmd)
--------------------------------------------------------





in myfile.m:
--------------------------------------------------------
#import "myfile.h"

implementation_NSString_Enum_Converters(Dispatch_chain_cmd)
--------------------------------------------------------


to use :


NSString *NSStringFromEnumDispatch_chain_cmd(enum Dispatch_chain_cmd value);


`NSStringFromEnumDispatch_chain_cmd(chain_for_c)` returns `@"chain_for_c"`



enum Dispatch_chain_cmd enumDispatch_chain_cmdFromNSString(NSString *value);



`enumDispatch_chain_cmdFromNSString(@"chain_previous")` returns `chain_previous`



Example 2: provide conversion routines for an existing enum
also demonstrates using a settings string, and renaming the typename used in the functions.



in myfile.h
--------------------------------------------------------

#import "NSStringFromEnum.h"


#define CAEdgeAntialiasingMask_SETTINGS_PARAMS CAEdgeAntialiasingMask,mask,EdgeMask,edgeMask

interface_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)

--------------------------------------------------------





in myfile.m:
--------------------------------------------------------

// we can put this in the .m file as we are not defining a typedef, just the strings.
#define define_CAEdgeAntialiasingMask(enum)\
enum(kCALayerLeftEdge)\
enum(kCALayerRightEdge)\
enum(kCALayerBottomEdge)\
enum(kCALayerTopEdge)



implementation_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)


Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through