Jak zdefiniować i używać ENUM w Objective-C?

180

Zadeklarowałem wyliczenie w moim pliku implementacyjnym, jak pokazano poniżej, i zadeklarowałem zmienną tego typu w moim interfejsie jako PlayerState thePlayerState; i użyłem zmiennej w moich metodach. Ale dostaję błędy stwierdzające, że nie jest to zadeklarowane. Jak poprawnie zadeklarować i użyć zmiennej typu PlayerState w moich metodach:

W pliku .m

@implementation View1Controller

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

w pliku .h:

@interface View1Controller : UIViewController {

    PlayerState thePlayerState;

w jakiejś metodzie w pliku .m:

-(void)doSomethin{

thePlayerState = PLAYER_OFF;

}
RexOnRoids
źródło
2
Teraz typem wyliczenia jestPlayerState. Czym staje się playerStateTypes?
user4951,
3
Aby uzyskać informacje na temat NS_ENUM i jego najnowszej nowoczesnej składni, zobacz publikację NS_ENUM & NS_OPTIONS autorstwa Mattta Thompsona.
Basil Bourque

Odpowiedzi:

109

Musisz typedefznajdować się w pliku nagłówkowym (lub innym pliku, który jest #importedytowany w nagłówku), ponieważ w przeciwnym razie kompilator nie będzie wiedział, jaki rozmiar utworzyć PlayerStateivar. Poza tym wydaje mi się to w porządku.

Dave DeLong
źródło
Opcja umieszczenia go w osobnym pliku wydawała mi się odpowiednia w moim przypadku. Nie wiem, czy to jest dobre podejście, ale musiałem użyć tego samego wyliczenia w dwóch różnych ViewControllerach (self i jego delegate / datasource). Importowanie nagłówka delegata / źródła danych spowodowało błąd i wydaje się zbyt duże, by zaspokoić zwykłą potrzebę. Więc stworzyłem nowy plik .h z zadeklarowanym wyliczeniem i zaimportowałem go zarówno do pliku viewControllers.h. Działa jak urok.
Leandro Alves
7
Powinien zalecić użycie makra NS_ENUM - ponieważ jest to najlepsza praktyka
khebbie
1
Musisz zadeklarować NS_ENUMwyliczenia za pomocą w Celu-C, jeśli chcesz, aby wyliczenie było dostępne w kodzie Swift.
smileyborg,
@DaveDeLong, czy to nadal obowiązuje w 2015 roku? Mam typedefzadeklarowany w .mpliku, który kompiluje się i działa dobrze.
Iulian Onofrei
@IulianOnofrei przejdzie do pliku .h, jeśli będziesz musiał użyć wyliczenia w innych plikach. Jeśli potrzebujesz go tylko w jednym pliku, umieszczenie go w pliku .m zawsze było w porządku.
Dave DeLong
206

Apple udostępnia makro, które pomaga zapewnić lepszą zgodność kodu, w tym Swift. Korzystanie z makra wygląda następująco.

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

Udokumentowane tutaj

rebelzach
źródło
Czy Obj C Enums może mieć zmienne składowe tak jak w Javie? Jeśli tak to jak?
kowal
Więc drugie rozwiązanie jest lepsze?
Iulian Onofrei
3
Drugie rozwiązanie jest lepsze (przy użyciu NS_ENUM), ponieważ jest bardziej nowoczesne i jest teraz wymagane w Objective-C, jeśli chcesz, aby twoje wyliczenie było dostępne w kodzie Swift.
smileyborg,
Zaktualizowano, aby pokazać, że drugie rozwiązanie jest w rzeczywistości lepsze.
rebelzach
W standardowej formie Apple nazwa typu jest powtarzana dla każdej wartości wyliczeniowej.
ThomasW,
29

W .h:

typedef enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
} PlayerState;
Ben Flynn
źródło
1
Taką odpowiedź możesz znaleźć w innych pytaniach SO, ale kiedy przeglądałem wyliczenia, pytanie to pojawiło się jako pierwsze, więc tutaj również dodałem odpowiedź.
Ben Flynn,
19

W przypadku bieżących projektów możesz użyć makra NS_ENUM()lub NS_OPTIONS().

typedef NS_ENUM(NSUInteger, PlayerState) {
        PLAYER_OFF,
        PLAYER_PLAYING,
        PLAYER_PAUSED
    };
Sean Woodward
źródło
2
... i co ważniejsze teraz, musisz zadeklarować NS_ENUMwyliczenia za pomocą w Objective-C, jeśli chcesz, aby wyliczenie było dostępne w kodzie Swift.
smileyborg,
16

Oto jak Apple robi to dla klas takich jak NSString:

W pliku nagłówkowym:

enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
};

typedef NSInteger PlayerState;

Zobacz Wskazówki dotyczące kodowania na stronie http://developer.apple.com/

Santhos
źródło
3
To nie pomaga OP. Chociaż technicznie poprawne, nie mówi im, jak stworzyć wyliczenie wielokrotnego użytku
RyanR
24
Linkowanie do developer.apple.com nie jest naprawdę pomocne. Czy jest jeszcze jakieś miejsce, które chciałbyś zacytować?
Brett,
Skopiuj / wklej dokumentację, która już została podana, link, który jest główną stroną, naprawdę nie pomaga innym ludziom ...
Onder OZCAN
3
To jest już nieaktualne, zobacz tę stronę developer.apple.com/library/ios/releasenotes/ObjectiveC/…
Alex Chesters
8

Polecam użycie NS_OPTIONS lub NS_ENUM. Możesz przeczytać więcej na ten temat tutaj: http://nshipster.com/ns_enum-ns_options/

Oto przykład z mojego własnego kodu używającego NS_OPTIONS, mam narzędzie, które ustawia podwarstwę (CALayer) na warstwie UIView w celu utworzenia granicy.

H. plik:

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

Plik .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
Johannes
źródło