Objective-Cで特定のタイプの列挙型を作成する正しい方法は何ですか? NS_ENUMとNS_OPTIONSはどのように機能しますか? NS_OPTIONSは、NSAutoresizingのようなマスクに使用されますか?ありがとう。
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
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
};
異なる種類の列挙を推測することを除いて、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;
このコードはC++/Objective-C++コンパイルでコンパイルできません。これは、aVarがタイプNSInteger
と見なされているが、MyEnumType1 | MyEnumType2
がタイプMyEnumType
であるため、この割り当ては、型キャスト、C++は暗黙的な型キャストを禁止しています。
現時点では、NS_OPTIONSが必要です。NS_OPTIONSはC++ 11の前に列挙型にフォールバックするため、実際にはMyEnumType
はありません。つまり、MyEnumType
はNSInteger
の単なる別名です。次のようなコード
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
NSInteger
をNSInteger
に割り当てているため、コンパイルされます。