2012-12-29 31 views
19

Objective-Cで特定の型の列挙型を作成する正しい方法は何ですか? NS_ENUMとNS_OPTIONSはどのように機能しますか? NS_OPTIONSはNSAutoresizingのようなマスクに使用されますか?ありがとう。Objective-C列挙型、NS_ENUM&NS_OPTIONS

Code from NSObjCRuntime.h 
    #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 
    #define NS_OPTIONS(_type, _name) _type _name; enum : _type 
+1

引用符付きコードはC++用に定義されています。 Cの定義は次のとおりです:#define NS_ENUM(_type、_name)_type _name; enum –

+0

以下の私の答えを確認してください。最初の答えは正しいですが、NS_OPTIONSとNS_ENUMの完全な違いはありません。 – CarmeloS

答えて

33

NSHipster。 NS_OPTIONSは、同様の方法で使用されるが、通常であろう列挙するためのビットを行う

代わりに

typedef enum { 
    UITableViewCellStyleDefault, 
    UITableViewCellStyleValue1, 
    UITableViewCellStyleValue2, 
    UITableViewCellStyleSubtitle 
} UITableViewCellStyle; 

又は

typedef enum { 
    UITableViewCellStyleDefault, 
    UITableViewCellStyleValue1, 
    UITableViewCellStyleValue2, 
    UITableViewCellStyleSubtitle 
}; 

typedef NSInteger UITableViewCellStyle; 

マスクこれ:

typedef NS_ENUM(NSInteger, UITableViewCellStyle) { 
    UITableViewCellStyleDefault, 
    UITableViewCellStyleValue1, 
    UITableViewCellStyleValue2, 
    UITableViewCellStyleSubtitle 
}; 

例NS_OPTIONS列挙型:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { 
    UIViewAutoresizingNone     = 0, 
    UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 
    UIViewAutoresizingFlexibleWidth  = 1 << 1, 
    UIViewAutoresizingFlexibleRightMargin = 1 << 2, 
    UIViewAutoresizingFlexibleTopMargin = 1 << 3, 
    UIViewAutoresizingFlexibleHeight  = 1 << 4, 
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5 
}; 
+0

しかし、NS_OPTIONSはどうですか? –

+0

NS_OPTIONSは同じように使用されていますが、列挙型の値ではなくビットマスクされた値を作成します – wattson12

+0

例を追加 – wattson12

8

異なる種類の列挙を除いて、2つの違いがあります。

のObjective-C++モードでコンパイルする場合、それらは異なるコードを生成する:

これは元のコードである:

typedef NS_OPTIONS(NSUInteger, MyOptionType) { 
    MyOptionType1 = 1 << 0, 
    MyOptionType2 = 1 << 1, 
}; 

typedef NS_ENUM(NSUInteger, MyEnumType) { 
    MyEnumType1 = 1 << 0, 
    MyEnumType2 = 1 << 1, 
}; 

これはマクロがObjective-Cコンパイルに展開されているコードである。

typedef enum MyOptionType : NSUInteger MyOptionType; enum MyOptionType : NSUInteger { 
    MyOptionType1 = 1 << 0, 
    MyOptionType2 = 1 << 1, 
}; 

typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger { 
    MyEnumType1 = 1 << 0, 
    MyEnumType2 = 1 << 1, 
}; 

Objective-C++のマクロ展開時のコードです。

typedef NSUInteger MyOptionType; enum : NSUInteger { 
    MyOptionType1 = 1 << 0, 
    MyOptionType2 = 1 << 1, 
}; 

typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger { 
    MyEnumType1 = 1 << 0, 
    MyEnumType2 = 1 << 1, 
}; 

2つのモードの間のNS_OPTIONSの違いを参照してください。

HERE IS THE REASON

C++ 11の新機能があり、あなたはその前に、型保持列挙は、列挙型の最大値に応じて、コンパイラによって決定され、あなたの列挙のための型を宣言することができます。 C++ 11でそう

、あなたが自分で列挙の大きさを決めることができるので、あなたはこのように、実際にそれらを定義せずに宣言列挙型を転送することができます:

//forward declare MyEnumType 
enum MyEnumType: NSInteger 

//use myEnumType 
enum MyEnumType aVar; 

//actually define MyEnumType somewhere else 
enum MyEnumType: NSInteger { 
    MyEnumType1 = 1 << 1, 
    MyEnumType2 = 1 << 2, 
} 

この機能は便利です、とObjective-C輸入この機能が、それは問題をもたらし、このように、ビット単位の計算を行うとき:

enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

このコードは、アヴァールはタイプNSIntegerで考慮されるが、MyEnumType1 | MyEnumType2がであるため、コンパイル++ C++/Objective-Cでコンパイルすることはできませんタイpe MyEnumType、この割り当ては型キャストなしでは実行できません。C++は暗黙型キャストを禁止します

enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

のようなそのコードがコンパイルされますので、この時点で、我々は実際に何MyEnumTypeがないようNS_OPTIONS、NS_OPTIONSは、C++ 11の前に戻って列挙にフォール必要がある、MyEnumTypeは、NSIntegerのためのちょうど別の名前でありますこれはNSIntegerNSIntegerに割り当てているためです。