enum typedef ใน Objective-C คืออะไร?


1087

ฉันไม่คิดว่าฉันเข้าใจในสิ่งที่เป็นenumอยู่และควรใช้เมื่อใด

ตัวอย่างเช่น:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

มีการประกาศอะไรที่นี่จริง ๆ ?


2
ผู้ใช้กำหนดชนิดที่เรียกว่า "enum" หรือไม่? นั่นคือสิ่งที่ฉันคิดจนกระทั่งฉันพบรหัสที่มีการประกาศ enum หลาย typedef
เครก

8
ไม่ชนิดที่ผู้ใช้กำหนดคือ ShapeType อ่านบน typedef: en.wikipedia.org/wiki/Typedef
rampion

6
typedef ใน Objective-C นั้นเหมือนกับ typedef ใน C และ enum ใน Objective-C นั้นเหมือนกับ enum ใน C สิ่งนี้ประกาศ enum ด้วยค่าคงที่สามค่าคงที่ kCircle = 0, kRectangle = 1 และ kOblateSpheroid = 2 และให้ enum พิมพ์ชื่อ ShapeType หากคุณไม่รู้ว่า "typedef" และ "enum" หมายถึงอะไรซื้อหนังสือเกี่ยวกับ C.
gnasher729

คำตอบ:


1565

สามสิ่งที่จะได้รับการประกาศที่นี่: ไม่ระบุชื่อระบุชนิดมีการประกาศShapeTypeจะถูกประกาศ typedef ที่แจงนับไม่ระบุชื่อและชื่อที่สามkCircle, kRectangleและkOblateSpheroidจะได้รับการประกาศให้เป็นค่าคงที่หนึ่ง

มาทำลายมันกันเถอะ ในกรณีที่ง่ายที่สุดการแจงนับสามารถประกาศเป็น

enum tagname { ... };

tagnameประกาศนี้นับมีแท็ก ใน C และ Objective-C (แต่ไม่ใช่ C ++) การอ้างอิงใด ๆ เกี่ยวกับสิ่งนี้จะต้องนำหน้าด้วยenumคำหลัก ตัวอย่างเช่น:

enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++

เพื่อหลีกเลี่ยงการใช้enumคำสำคัญทุกที่สามารถพิมพ์ typedef:

enum tagname { ... };
typedef enum tagname tagname;  // declare 'tagname' as a typedef for 'enum tagname'

สิ่งนี้สามารถทำให้เป็นบรรทัดเดียวได้ง่าย:

typedef enum tagname { ... } tagname;  // declare both 'enum tagname' and 'tagname'

และสุดท้ายหากเราไม่จำเป็นต้องสามารถใช้enum tagnameกับenumคำหลักเราสามารถทำให้enumไม่ระบุชื่อและประกาศด้วยชื่อ typedef เท่านั้น:

typedef enum { ... } tagname;

ตอนนี้ในกรณีนี้เรากำลังประกาศShapeTypeให้เป็นชื่อที่พิมพ์โดยไม่มีการระบุชื่อ ShapeTypeเป็นจริงเพียงชนิดหนึ่งและควรจะใช้เฉพาะกับตัวแปรประกาศซึ่งถือเป็นหนึ่งในค่าที่ระบุไว้ในประกาศ (นั่นคือหนึ่งkCircle, kRectangleและkOblateSpheroid) คุณสามารถกำหนดShapeTypeตัวแปรอีกค่าได้โดยการร่ายดังนั้นคุณต้องระวังเมื่ออ่านค่า enum

สุดท้ายkCircle, kRectangleและkOblateSpheroidได้รับการประกาศให้เป็นค่าคงที่สำคัญใน namespace โลก เนื่องจากไม่มีการระบุค่าเฉพาะพวกเขาจะได้รับมอบหมายให้เป็นจำนวนเต็มต่อเนื่องโดยเริ่มต้นด้วย 0 ดังนั้นkCircle0 kRectangleคือ 1 และkOblateSpheroid2


6
คำอธิบายที่ดี - เพียงเพิ่มสิ่งหนึ่งแล้ว struct ทำตามกฎการตั้งชื่อที่คล้ายกันใน C (ไม่แน่ใจเกี่ยวกับ Objective-C)
ไมเคิลเสี้ยน

109
Objective-C เป็น superset ที่เหมาะสมของ C กฎการตั้งชื่อโครงสร้าง C ทั้งหมดใน C นั้นใช้ได้ใน Objective-C
sigjuice

น่ากลัว ฉันสามารถใช้สไตล์ C ++ ได้ไหมและไม่ต้องเขียน enum อีกด้วย :)
user4951

11
คุณสามารถใช้สไตล์ C ++ enums หากไฟล์ที่คุณประกาศเป็นไฟล์. mm แทนที่จะเป็น. m Objective-C ++ นั้นทรงพลังอย่างเหลือเชื่อ
Kevin Hoffman

14
และเมื่อคุณเข้าใจคำตอบนี้แล้วมันก็คุ้มค่าที่จะดู NS_ENUM และ NS_OPTIONS ใหม่ บทเรียนที่นี่: nshipster.com/ns_enum-ns_optionsและอื่น ๆ ที่นี่: stackoverflow.com/questions/14080750/…
Snowcrash

254

Apple แนะนำให้นิยาม enums เช่นนี้ตั้งแต่Xcode 4.4 :

typedef enum ShapeType : NSUInteger {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

พวกเขายังให้มาโครที่ใช้งานง่ายNS_ENUM:

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

คำจำกัดความเหล่านี้ให้การตรวจสอบประเภทที่เข้มงวดยิ่งขึ้นและการกรอกโค้ดที่ดีขึ้น ฉันไม่สามารถหาเอกสารอย่างเป็นทางการของNS_ENUMแต่คุณสามารถชม "โมเดิร์น Objective-C" วิดีโอจากงาน WWDC 2012 เซสชั่นที่นี่


UPDATE
เชื่อมโยงไปยังเอกสารอย่างเป็นทางการที่นี่


13
ส่วนเกี่ยวกับ "การปรับปรุง Enum" เริ่มต้นที่ 5:58
vikingosegundo

5
ตามที่แสดงความคิดเห็นในคำตอบอื่น ๆ โปรดดูคำอธิบายของNS_ENUMมาโครของ Apple โดย NSHipster: NSHipster.com/ns_enum-ns_options
Basil Bourque

1
นี่คือลิงค์ไปยังเอกสารอย่างเป็นทางการเกี่ยวกับ NS_ENUM: developer.apple.com/library/ios/releasenotes/ObjectiveC/…
YoGiN

50

Enum ประกาศชุดของค่าที่สั่ง - typedef เพิ่งเพิ่มชื่อที่มีประโยชน์ให้กับสิ่งนี้ องค์ประกอบที่ 1 คือ 0 เป็นต้น

typedef enum {
Monday=1,
...
} WORKDAYS;

WORKDAYS today = Monday;

ด้านบนเป็นเพียงการนับแท็ก shapeType


34

ผู้ใช้กำหนดชนิดที่มีค่าที่เป็นไปได้ของkCircle, หรือkRectangle kOblateSpheroidแม้ว่าค่าภายใน enum (kCircle ฯลฯ ) จะมองเห็นได้นอก enum สิ่งสำคัญคือต้องคำนึงถึงสิ่งนั้น ( int i = kCircle;เช่นถูกต้อง)


30

อัพเดตสำหรับการเปลี่ยนแปลง 64 บิต: ตามเอกสารของ Appleเกี่ยวกับการเปลี่ยนแปลง 64 บิต

การแจกแจงจะถูกพิมพ์ด้วยเช่นกัน: ในคอมไพเลอร์ LLVM ประเภทการแจกแจงสามารถกำหนดขนาดของการแจงนับได้ ซึ่งหมายความว่าบางประเภทระบุอาจมีขนาดที่ใหญ่กว่าที่คุณคาดไว้ วิธีการแก้ปัญหาดังเช่นในกรณีอื่น ๆ ทั้งหมดคือการไม่มีข้อสมมติฐานเกี่ยวกับขนาดของชนิดข้อมูล ให้กำหนดค่าที่แจกแจงให้กับตัวแปรด้วยชนิดข้อมูลที่เหมาะสมแทน

ดังนั้นคุณต้องสร้าง enum พร้อมกับประเภทดังนี้ไวยากรณ์ถ้าคุณรองรับ 64- บิต

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

หรือ

typedef enum ShapeType : NSUInteger {
   kCircle,
   kRectangle,
   kOblateSpheroid
} ShapeType;

มิฉะนั้นจะนำไปสู่การเตือนเป็น Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

อัพเดตสำหรับการตั้งโปรแกรมแบบ swift:

รวดเร็วมีการเปลี่ยนแปลงทางไวยากรณ์

enum ControlButtonID: NSUInteger {
        case kCircle , kRectangle, kOblateSpheroid
    }

หากจำเป็นที่จะต้องไปข้างหน้าประกาศ enum (NS_ENUM): stackoverflow.com/a/42009056/342794
Lal

25

enum (ตัวย่อของการแจงนับ) ใช้เพื่อแจกแจงชุดของค่า (enumerators) ค่าคือสิ่งที่เป็นนามธรรมแสดงด้วยสัญลักษณ์ (คำ) ตัวอย่างเช่น enum พื้นฐานอาจเป็น

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };

enum นี้เรียกว่าไม่ระบุชื่อเนื่องจากคุณไม่มีสัญลักษณ์ชื่อ แต่มันก็ยังถูกต้องสมบูรณ์ แค่ใช้มันแบบนี้

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;

ตกลง. ชีวิตมีความสวยงามและทุกอย่างเป็นไปด้วยดี แต่วันหนึ่งคุณต้องใช้ enum นี้ซ้ำเพื่อกำหนดตัวแปรใหม่เพื่อเก็บ myGrandFatherPantSize จากนั้นคุณเขียน:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;

แต่คุณมีข้อผิดพลาดคอมไพเลอร์ "นิยามใหม่ของตัวแจงนับ" ที่จริงแล้วปัญหาคือคอมไพเลอร์ไม่แน่ใจว่าคุณ enum แรกและคุณเป็นคนที่สองอธิบายสิ่งเดียวกัน

ถ้าคุณต้องการใช้ชุดตัวแจงนับซ้ำ (ที่นี่ xs ... xxxxl) ในหลาย ๆ ที่คุณต้องติดแท็กด้วยชื่อที่ไม่ซ้ำกัน ครั้งที่สองที่คุณใช้ชุดนี้คุณเพียงแค่ต้องใช้แท็ก แต่อย่าลืมว่าแท็กนี้ไม่ได้แทนที่คำ enum แต่เป็นเพียงชุดของตัวแจงนับ จากนั้นดูแลให้ใช้ enum ตามปกติ แบบนี้:

// Here the first use of my enum
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize; 
// here the second use of my enum. It works now!
enum sizes myGrandFatherPantSize;

คุณสามารถใช้มันในการกำหนดพารามิเตอร์เช่นกัน:

// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;

คุณสามารถพูดได้ว่าการเขียนซ้ำ enum ไม่สะดวกและทำให้โค้ดดูแปลกไป คุณพูดถูก ประเภทที่แท้จริงจะดีกว่า

นี่เป็นขั้นตอนสุดท้ายของการก้าวไปสู่การประชุมสุดยอดครั้งใหญ่ของเรา เพียงแค่เพิ่ม typedef ลองเปลี่ยน enum ของเราแบบจริง โอ้สิ่งสุดท้ายไม่อนุญาตให้พิมพ์ typef ในชั้นเรียนของคุณ จากนั้นกำหนดประเภทของคุณด้านบน ทำเช่นนี้:

// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type

@interface myClass {
   ...
   size_type myGrandMotherDressSize, myGrandFatherPantSize;
   ...
}

จำไว้ว่าแท็กเป็นตัวเลือก จากนั้นที่นี่ในกรณีนี้เราไม่ติดแท็กตัวแจงนับ แต่เพียงเพื่อกำหนดประเภทใหม่ จากนั้นเราไม่ต้องการมันอีกต่อไป

// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;

@interface myClass : NSObject {
  ...
  size_type myGrandMotherDressSize, myGrandFatherPantSize;
  ...
}
@end

หากคุณกำลังพัฒนาใน Objective-C ด้วย XCode ฉันจะให้คุณค้นพบมาโครที่ดีบางตัวที่นำหน้าด้วย NS_ENUM ที่จะช่วยให้คุณกำหนด enums ที่ดีได้ง่ายและยิ่งกว่านั้นจะช่วยให้ตัววิเคราะห์แบบคงที่ทำการตรวจสอบที่น่าสนใจสำหรับคุณก่อนที่จะรวบรวม

ดี Enum!


ฉันมักจะคิดว่า "ทำไมทุกคนจะตอบคำถามที่ตอบแล้วได้รับการยอมรับ" เด็กชายฉันผิดตลอดเวลา! นี่คือคำตอบที่ดีที่สุดและช่วยให้ผู้เริ่มต้นอย่างฉัน!
rak appdev

10

typedefมีประโยชน์สำหรับการกำหนดชื่อตัวแปรชนิดที่มีอยู่ใหม่ มันมีวิธีสั้น ๆ และมีความหมายในการเรียกประเภทข้อมูล เช่น:

typedef unsigned long int TWOWORDS;

นี่ int ชนิดยาวที่ไม่ได้ลงนามจะถูกกำหนดให้เป็นประเภท TWOWORDS ดังนั้นตอนนี้เราสามารถประกาศตัวแปรประเภท int ไม่ได้ลงนามยาวโดยการเขียน

TWOWORDS var1, var2;

แทน

unsigned long int var1, var2;

7
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

จากนั้นคุณสามารถใช้มันเช่น: -

 ShapeType shape;

และ

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

ตอนนี้คุณสามารถใช้มันเหมือน: -

enum ShapeType shape;

3

enum ใช้เพื่อกำหนดค่าให้กับองค์ประกอบ enum ซึ่งไม่สามารถทำได้ใน struct ดังนั้นทุกครั้งแทนที่จะเข้าถึงตัวแปรทั้งหมดเราสามารถทำได้โดยค่าที่เรากำหนดให้กับตัวแปรใน enum โดยค่าเริ่มต้นมันเริ่มต้นด้วยการกำหนดค่า 0 แต่เราสามารถกำหนดค่าใดก็ได้และตัวแปรถัดไปใน enum จะถูกกำหนดค่าให้กับค่าก่อนหน้า +1


3

คุณสามารถใช้ในรูปแบบด้านล่างค่าเริ่มต้นแบบดิบเริ่มต้นที่ 0 ดังนั้น

  • kCircle คือ 0
  • kRectangle คือ 1
  • kOblateSpheroid คือ 2

คุณสามารถกำหนดค่าเริ่มต้นเฉพาะของคุณเอง

typedef enum : NSUInteger {
    kCircle, // for your value; kCircle = 5, ...
    kRectangle,
    kOblateSpheroid
} ShapeType;

ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0

2

typedef อนุญาตให้โปรแกรมเมอร์กำหนดหนึ่งประเภท Objective-C เป็นอีกประเภทหนึ่ง ตัวอย่างเช่น,

typedef int ตัวนับ; กำหนดประเภทเคาน์เตอร์จะเทียบเท่ากับประเภท int สิ่งนี้ช่วยปรับปรุงความสามารถในการอ่านโค้ดอย่างมาก


2

Typedef เป็นคำสำคัญใน C และ C ++ มันถูกใช้เพื่อสร้างชื่อใหม่สำหรับชนิดข้อมูลพื้นฐาน(ถ่าน, int ลอยคู่ struct & enum)

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

ที่นี่สร้างประเภทข้อมูลที่แจกแจงShapeType & เราสามารถเขียนชื่อใหม่สำหรับประเภท Enum ShapeTypeตามที่ระบุด้านล่าง

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;

1

enum สามารถลด "ข้อผิดพลาด" ได้หลายประเภทและทำให้รหัสสามารถจัดการได้ง่ายขึ้น

#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER

คำจำกัดความไม่มีข้อ จำกัด มันเป็นเพียงการทดแทน ไม่สามารถ จำกัด เงื่อนไขทั้งหมดของรัฐได้ เมื่อ STATE ถูกกำหนดเป็น 5 โปรแกรมจะผิดเพราะไม่มีสถานะที่ตรงกัน แต่คอมไพเลอร์จะไม่เตือน STATE = 5

ดังนั้นจึงเป็นการดีกว่าที่จะใช้เช่นนี้

typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.