Question

I have a large enum (for the sake of transparency 63 values), and I am now creating a NS_Options bitflag based on that enum. Is there a way that I can write this so that it will be flexible?

The main concerns I have with hardcoding it are:

  • If I add/remove an enum, I will have to manually add/remove it in my bitflag.
  • There is a lot of typing to generate these.
  • My .h file is getting intensely long (because I like to use whitespace and adequate comments)

The only solution I've come up with thus far is:

#define FlagForEnum(enum) 1 << enum

typedef NS_ENUM(NSInteger, ExampleEnum)
{
    Value1,
    Value2,
    ...
    ValueN
}

typedef NS_OPTIONS(NSNumber, ExampleEnumFlags)
{
    Value1Flag = FlagForEnum(Value1),
    Value2Flag = FlagForEnum(Value2),
    ...
    ValueNFlag = FlagForEnum(ValueN)
}

This is a barely adequate solution when I remove an enum (at least I get a compile error), and if the enum ordering gets changed, the flags' bitshifted position changes too (not that it truly matters, but it seems comforting). But it doesn't solve the 'this-is-a-lot-of-typing' problem, or the 'what-if-I-forget-to-add-a-flag' problem.

Was it helpful?

Solution

You can use a technique called X Macro

#define VALUES \
  VALUE_LINE(Value1) \
  VALUE_LINE(Value2) \
  VALUE_LINE(Value3)

typedef NS_ENUM(NSUInteger, ExampleEnum)
{
#define VALUE_LINE(x) x,
VALUES
#undef VALUE_LINE
}

typedef NS_OPTIONS(NSUInteger, ExampleEnumFlags)
{
#define VALUE_LINE(x) x##Flag = 1 << x,
VALUES
#undef VALUE_LINE
}

OTHER TIPS

Here is a slightly better (in terms of less typing) preprocessor #define solution. Although this still isn't as elegant as I'd like.

#define BitShift(ENUM_ATTRIBUTE)            (1 << ENUM_ATTRIBUTE)
#define CreateEnumFlag(ENUM_ATTRIBUTE)      ENUM_ATTRIBUTE##Flag = BitShift(ENUM_ATTRIBUTE)

typedef NS_ENUM(NSUInteger, ExampleEnum)
{
    Value1,
    Value2,
    ...
    ValueN
}

typedef NS_Options(NSUInteger, ExampleEnumFlags)
{
    CreateEnumFlag(Value1),
    CreateEnumFlag(Value2),
    ...
    CreateEnumFlag(ValueN)
}

This will create flags of the form Value1Flag, Value2Flag, ..., ValueNFlag.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top