2012-12-29 11 views
19

Cách chính xác để tạo một kiểu liệt kê với một kiểu cụ thể trong Objective-C là gì? NS_ENUM và NS_OPTIONS hoạt động như thế nào? NS_OPTIONS được sử dụng cho mặt nạ, như NSAutoresizing? Cảm ơn.Enzeration mục tiêu-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

Mã được trích dẫn được xác định cho C++. Định nghĩa C là: #define NS_ENUM (_type, _name) _type _name; enum –

+0

Hãy chắc chắn để kiểm tra câu trả lời của tôi dưới đây, câu trả lời đầu tiên là đúng, nhưng nó đã không cung cấp cho sự khác biệt đầy đủ giữa NS_OPTIONS và NS_ENUM. – CarmeloS

Trả lời

33

ví dụ từ NSHipster. NS_OPTIONS được sử dụng trong một cách tương tự, nhưng đối với enums mà thông thường sẽ là một chút mặt nạ

thay vì

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

hoặc

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

typedef NSInteger UITableViewCellStyle; 

làm điều này:

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

một ví dụ NS_OPTIONS enum:

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

Nhưng còn NS_OPTIONS thì sao? –

+0

như tôi đã nói, NS_OPTIONS được sử dụng theo cùng một cách, nhưng nó sẽ tạo ra các giá trị được che bằng bit thay vì các giá trị enum tăng thêm – wattson12

+0

thêm một ví dụ – wattson12

8

Có sự khác biệt giữa hai loại trừ khi chúng suy ra các loại liệt kê khác nhau.

Khi biên soạn trong ++ chế độ-C Mục tiêu, họ tạo ra mã khác nhau:

này là mã gốc:

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

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

đây là mã khi macro được mở rộng trong Objective-C biên dịch:

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

đây là mã khi macro được mở rộng trong Objective-C++ biên dịch:

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

Xem sự khác biệt của NS_OPTIONS giữa hai chế độ?

HERE IS THE REASON:

Có một tính năng mới trong C++ 11, bạn có thể khai báo một kiểu cho bạn liệt kê, trước đó, các loại cổ phần liệt kê được quyết định bởi trình biên dịch theo giá trị lớn nhất của kiểu liệt kê.

Vì vậy, trong C++ 11, kể từ khi bạn có thể quyết định kích thước của liệt kê của bạn bằng chính mình, bạn có thể chuyển tiếp tuyên bố enums mà không thực sự xác định chúng, như thế này:

//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, 
} 

Tính năng này rất thuận tiện, và Objective-C hàng nhập khẩu tính năng này, nhưng nó mang lại một vấn đề, khi thực hiện tính toán trên bit, như thế này:

enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

mã này không thể biên dịch C++/Objective-C++, vì Avar được coi là loại NSInteger nhưng MyEnumType1 | MyEnumType2 là ty pe MyEnumType, nhiệm vụ này không thể thực hiện mà không có dàn diễn viên kiểu, C++ cấm loại đúc ẩn.

Tại thời điểm này, chúng ta cần NS_OPTIONS, NS_OPTIONS rơi trở lại enum trước C++ 11, do đó không có MyEnumType thực sự, MyEnumType chỉ là một tên khác cho NSInteger, do đó mã như

enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

sẽ biên dịch , vì nó được chỉ định NSInteger đến NSInteger.