ฉันจะกำหนดและใช้ ENUM ใน Objective-C ได้อย่างไร


180

ฉันประกาศ enum ในไฟล์การใช้งานของฉันตามที่แสดงด้านล่างและประกาศตัวแปรประเภทนั้นในส่วนต่อประสานของฉันเป็น PlayerState thePlayerState; และใช้ตัวแปรในวิธีการของฉัน แต่ฉันได้รับข้อผิดพลาดที่ระบุว่าไม่ได้ประกาศ ฉันจะประกาศอย่างถูกต้องและใช้ตัวแปรประเภท PlayerState ในวิธีการของฉันได้อย่างไร:

ในไฟล์. m

@implementation View1Controller

    typedef enum playerStateTypes
        {
            PLAYER_OFF,
            PLAYER_PLAYING,
            PLAYER_PAUSED
        } PlayerState;

ในไฟล์. h:

@interface View1Controller : UIViewController {

    PlayerState thePlayerState;

ในวิธีการบางอย่างในไฟล์. m:

-(void)doSomethin{

thePlayerState = PLAYER_OFF;

}

2
ตอนนี้ชนิดของ enum คือ thePlayerState playerStateTypes เกิดอะไรขึ้น?
user4951

3
สำหรับข้อมูลเกี่ยวกับ NS_ENUM และไวยากรณ์ที่ทันสมัยล่าสุดให้ดูที่การโพสต์NS_ENUM & NS_OPTIONSโดย Mattt Thompson
Basil Bourque

คำตอบ:


109

คุณtypedefต้องอยู่ในไฟล์ส่วนหัว (หรือไฟล์อื่น ๆ ที่#importอยู่ในส่วนหัวของคุณ) เพราะมิฉะนั้นคอมไพเลอร์จะไม่ทราบขนาดที่จะทำให้PlayerStateivar นอกเหนือจากนั้นมันก็โอเคสำหรับฉัน


ตัวเลือกที่จะใส่ไว้ในไฟล์แยกต่างหากนั้นถูกต้องในกรณีของฉัน ฉันไม่รู้ว่านี่เป็นวิธีการที่ดีหรือไม่ แต่ฉันต้องการใช้ enum เดียวกันใน ViewControllers สองแบบ (ด้วยตนเองและเป็นตัวแทน / แหล่งข้อมูล) การนำเข้าส่วนหัวของผู้รับมอบสิทธิ์ / แหล่งข้อมูลทำให้เกิดข้อผิดพลาดและดูเหมือนจะมากเกินไปสำหรับความต้องการที่เรียบง่าย ดังนั้นฉันจึงสร้างไฟล์. h ใหม่พร้อมประกาศ enum และนำเข้าไฟล์ทั้งในไฟล์ viewControllers.h ทำงานเหมือนจับใจ
Leandro Alves

7
ควรแนะนำให้ใช้มาโคร NS_ENUM - เนื่องจากนี่เป็นแนวทางปฏิบัติที่ดีที่สุด
khebbie

1
คุณต้องประกาศ enums ที่ใช้NS_ENUMใน Objective-C หากคุณต้องการให้ enum ของคุณพร้อมใช้งานในรหัส Swift
smileyborg

@DaveDeLong สิ่งนี้ยังใช้ได้ในปี 2558 หรือไม่? ฉันมีการtypedefประกาศใน.mไฟล์และมันรวบรวมและทำงานได้ดี
Iulian Onofrei

@IulianOnofrei มันจะไปในไฟล์. h หากคุณต้องการใช้ enum ในไฟล์อื่น ๆ หากคุณต้องการเพียงไฟล์เดียวการวางไว้ในไฟล์. m นั้นใช้ได้อย่างสมบูรณ์แบบเสมอ
เดฟ DeLong

206

Apple จัดให้มีแมโครเพื่อช่วยให้ใช้งานร่วมกับโค้ดได้ดีขึ้นรวมถึง Swift การใช้แมโครมีลักษณะเช่นนี้

typedef NS_ENUM(NSInteger, PlayerStateType) {
  PlayerStateOff,
  PlayerStatePlaying,
  PlayerStatePaused
};

เอกสารที่นี่


Obj C Enums สามารถมีตัวแปรสมาชิกอย่างที่สามารถทำได้ใน Java หรือไม่? ถ้าเป็นเช่นนั้นได้อย่างไร
กุญแจ

ดังนั้นทางออกที่สองจะดีกว่า
Iulian Onofrei

3
วิธีที่สองนั้นดีกว่า (โดยใช้NS_ENUM) เนื่องจากมันทันสมัยกว่าและตอนนี้จำเป็นต้องใช้ใน Objective-C หากคุณต้องการให้ enum ของคุณพร้อมใช้งานใน Swift code
smileyborg

อัปเดตเพื่อแสดงโซลูชันที่สองในความเป็นจริงดีกว่า
rebelzach

ในรูปแบบมาตรฐานของ Apple ชื่อชนิดจะถูกทำซ้ำสำหรับแต่ละค่า enum
ThomasW

29

ใน. h:

typedef enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
} PlayerState;

1
คุณสามารถหาคำตอบเช่นนี้ในคำถาม SO อื่น ๆ แต่เมื่อฉันตรวจสอบ enums คำถามนี้โผล่ขึ้นมาก่อนดังนั้นฉันจึงเพิ่มคำตอบที่นี่ด้วย
Ben Flynn

19

สำหรับโครงการปัจจุบันคุณอาจต้องการใช้งานNS_ENUM()หรือNS_OPTIONS()แมโคร

typedef NS_ENUM(NSUInteger, PlayerState) {
        PLAYER_OFF,
        PLAYER_PLAYING,
        PLAYER_PAUSED
    };

2
... และที่สำคัญตอนนี้คุณต้องประกาศ enums ที่ใช้NS_ENUMใน Objective-C หากคุณต้องการให้ enum ของคุณพร้อมใช้งานใน Swift code
smileyborg

16

นี่คือวิธีที่ Apple ใช้กับคลาสอย่าง NSString:

ในไฟล์ส่วนหัว:

enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
};

typedef NSInteger PlayerState;

อ้างถึงแนวทางการเข้ารหัสที่http://developer.apple.com/


3
สิ่งนี้ไม่ได้ช่วย OP จริง ๆ ในขณะที่ถูกต้องทางเทคนิคมันไม่ได้บอกพวกเขาถึงวิธีการสร้าง enum ที่ใช้ซ้ำได้
RyanR

24
การเชื่อมโยงไปยัง developer.apple.com ไม่เป็นประโยชน์จริง ๆ มีสถานที่อื่นที่คุณต้องการอ้างอิงแทนหรือไม่
เบร็ท

คัดลอก / วางเอกสารที่ให้มาแล้วลิงค์ซึ่งเป็นหน้าหลักไม่ช่วยคนอื่น ...
Onder OZCAN

3
นี่ล้าสมัยแล้วดูหน้านี้developer.apple.com/library/ios/releasenotes/ObjectiveC/
......

8

ฉันแนะนำให้ใช้ NS_OPTIONS หรือ NS_ENUM คุณสามารถอ่านเพิ่มเติมได้ที่นี่: http://nshipster.com/ns_enum-ns_options/

นี่คือตัวอย่างจากรหัสของฉันเองโดยใช้ NS_OPTIONS ฉันมียูทิลิตี้ที่ตั้งค่าเลเยอร์ย่อย (CALayer) บนเลเยอร์ของ UIView เพื่อสร้างเส้นขอบ

ชั่วโมง ไฟล์:

typedef NS_OPTIONS(NSUInteger, BSTCMBorder) {
    BSTCMBOrderNoBorder     = 0,
    BSTCMBorderTop          = 1 << 0,
    BSTCMBorderRight        = 1 << 1,
    BSTCMBorderBottom       = 1 << 2,
    BSTCMBOrderLeft         = 1 << 3
};

@interface BSTCMBorderUtility : NSObject

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color;

@end

ไฟล์. m:

@implementation BSTCMBorderUtility

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color
{

    // Make a left border on the view
    if (border & BSTCMBOrderLeft) {

    }

    // Make a right border on the view
    if (border & BSTCMBorderRight) {

    }

    // Etc

}

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