Objective-C'de typedef enum nedir?


1087

An'ın ne enumolduğunu ve ne zaman kullanılacağını temelde anladığımı sanmıyorum .

Örneğin:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Burada gerçekten ne ilan ediliyor?


2
Kullanıcı tanımlı tür "enum" mu? Birden çok typedef enum bildirimi olan bir kodla karşılaşana kadar böyle düşünmüştüm.
Craig

8
Hayır, kullanıcı tanımlı tip ShapeType'tır.
Typedef hakkında bilgi edinin

6
Objective-C'deki bir typedef, C'deki bir typedef ile tam olarak aynıdır. Objective-C'deki bir enum, C'deki bir enum ile tamamen aynıdır. Bu, kCircle = 0, kRectangle = 1 ve kOblateSpheroid = 2 ve enum türüne ShapeType adını verir. "Typedef" ve "enum" ne anlama geldiğini bilmiyorsanız, C hakkında bir kitap satın alın.
gnasher729

Yanıtlar:


1565

İsimsiz bir numaralandırılmış tipi bildirildi: Üç şey burada beyan ediliyor ShapeTypeisimsiz sayımı için bir typedef ilan ediliyor ve üç isim kCircle, kRectangleve kOblateSpheroidayrılmaz sabitleri olarak ilan edilmektedir.

Bunu parçalayalım. En basit durumda, bir numaralandırma şu şekilde ilan edilebilir:

enum tagname { ... };

Bu, etiketle bir numaralandırma bildirir tagname. C ve Objective-C (ama içinde değil C ++), bu ilişkili başvurular gerekir ile gelmelidir enumanahtar kelime. Örneğin:

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

enumAnahtar kelimeyi her yerde kullanmak zorunda kalmamak için bir typedef oluşturulabilir:

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

Bu tek bir satıra sadeleştirilebilir:

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

Ve biz kullanmak gerekiyor yoksa son olarak, enum tagnamebirlikte enumanahtar kelime, biz yapabilir enumanonim ve tek typedef adı ile beyan:

typedef enum { ... } tagname;

Şimdi, bu durumda, ShapeTypeanonim bir numaralandırmanın tip tanımlı bir adı olduğunu beyan ediyoruz . ShapeTypegerçekten sadece ayrılmaz bir türüdür ve sadece (bir birini bildiriminde listelenen değerlerden birini tutmak değişkenleri bildirmek için kullanılması gerektiğini kCircle, kRectangleve kOblateSpheroid). ShapeTypeBununla birlikte, bir değişkeni başka bir değer atayarak atayabilirsiniz , bu nedenle numaralandırma değerlerini okurken dikkatli olmanız gerekir.

Son olarak, kCircle, kRectangle, ve kOblateSpheroidgenel ad ayrılmaz sabitleri olarak ilan edilir. Belirli bir değer belirtilmediğinden, 0 ile başlayan ardışık tamsayılara atanırlar, yani kCircle0, kRectangle1 ve kOblateSpheroid2'dir.


6
Güzel bir açıklama - sadece bir şey eklemek için, yapıların C'deki benzer adlandırma kurallarına uyması (Objective-C'den emin değilim).
Michael Burr

109
Objective-C, C'nin uygun bir üst kümesidir. C'deki tüm C yapı adlandırma kuralları Objective-C için de geçerlidir.
sigjuice

Muhteşem. Sadece C ++ tarzı enum kullanabilir miyim ve ayrıca enum yazmanıza gerek yok :)
user4951

11
Onları bildirdiğiniz dosya bir .m yerine bir .mm dosyası ise C ++ stili numaralandırmaları kullanabilirsiniz. Objective-C ++ saçma bir şekilde güçlü.
Kevin Hoffman

14
Ve bir kez bu cevabı bulduğunuzda, yeni NS_ENUM ve NS_OPTIONS'a bakmaya değer. Öğretici burada: nshipster.com/ns_enum-ns_options ve burada SO: stackoverflow.com/questions/14080750/…
Snowcrash

254

Apple, Xcode 4.4'ten beri böyle numaraların tanımlanmasını önerir :

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

Ayrıca kullanışlı bir makro sağlarlar NS_ENUM:

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

Bu tanımlar daha güçlü tip kontrolü ve daha iyi kod tamamlama sağlar. Ben resmi belgelerine bulamadı NS_ENUMama WWDC 2012 oturumdan "Modern Objective-C" video izleyebilirsiniz burada .


GÜNCELLEME Burada
resmi belgelere bağlantı .


13
"Enum İyileştirmeleri" ile ilgili bölüm 5:58
vikingosegundo

5
Başka bir yanıta yorum olarak, Apple'ın NS_ENUMmakrosunun NSHipster tarafından yapılan açıklamasına bakın : NSHipster.com/ns_enum-ns_options
Basil Bourque

1
Bu, NS_ENUM ile ilgili resmi belgelere bağlantıdır: developer.apple.com/library/ios/releasenotes/ObjectiveC/…
YoGiN

50

Bir enum bir dizi sıralı değer bildirir - typedef buna kullanışlı bir isim ekler. 1. eleman 0 vb.

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

WORKDAYS today = Monday;

Yukarıdakiler sadece shapeType etiketlerinin numaralandırmasıdır.


34

Olası değerler içeren bir kullanıcı tanımlı tür kCircle, kRectangleya da kOblateSpheroid. Numaralandırma içindeki değerler (kCircle, vb.) Numaralandırmanın dışında görülebilir. Bunu akılda tutmak önemlidir ( int i = kCircle;örneğin geçerlidir).


30

64 bitlik değişiklik için güncelleme: Apple belgelerine göre yaklaşık 64 bitlik değişiklikler,

Numaralandırmalar da Yazılır: LLVM derleyicisinde numaralandırılmış türler numaralandırmanın boyutunu tanımlayabilir. Bu, bazı numaralandırılmış türlerin de beklediğinizden daha büyük bir boyuta sahip olabileceği anlamına gelir. Çözüm, diğer tüm durumlarda olduğu gibi, bir veri türünün boyutu hakkında hiçbir varsayımda bulunmamaktır. Bunun yerine, doğru veri türüne sahip bir değişkene numaralandırılmış değerleri atayın

Bu yüzden 64-bit için destekliyorsanız, aşağıdaki sözdiziminde tür ile enum oluşturmalısınız .

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

veya

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

Aksi takdirde, Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Hızlı programlama için güncelleme:

Hızlıca bir sözdizimi değişikliği var.

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

Enum bildirmek gerekirse (NS_ENUM): stackoverflow.com/a/42009056/342794
lal

25

Numaralandırma (numaralandırmanın kısaltması) bir dizi değeri (numaralandırıcılar) numaralandırmak için kullanılır. Değer, bir sembolle (kelime) temsil edilen soyut bir şeydir. Örneğin, temel bir numaralandırma

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

Bu numaralandırma anonim olarak adlandırılır, çünkü bunu adlandırmak için bir sembolünüz yoktur. Ama yine de tamamen doğru. Sadece böyle kullan

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

Tamam. Hayat güzel ve her şey yolunda gidiyor. Ancak bir gün myGrandFatherPantSize'ı depolamak için yeni bir değişken tanımlamak için bu numaralandırmayı yeniden kullanmanız gerekir, sonra şunu yazın:

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

Ama sonra derleyici hatası "numaralandırıcı yeniden tanımlama" var. Aslında sorun, derleyicinin ilk numaralandırdığınızdan ve ikinci olarak da aynı şeyi tanımladığından emin olmamasıdır.

Daha sonra aynı numaralandırıcı setini (burada xs ... xxxxl) birkaç yerde yeniden kullanmak istiyorsanız, benzersiz bir adla etiketlemelisiniz. Bu seti ikinci kez kullandığınızda etiketi kullanmanız yeterlidir. Ancak bu etiketin numaralandırma sözcüğü yerine yalnızca numaralandırma kümesinin yerini aldığını unutmayın. Sonra enum'u her zamanki gibi kullanmaya dikkat edin. Bunun gibi:

// 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;

bir parametre tanımında da kullanabilirsiniz:

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

Her yerde enum'u yeniden yazmanın uygun olmadığını ve kodun biraz garip görünmesini sağlayabilirsiniz. Haklısın. Gerçek bir tür daha iyi olurdu.

Bu zirveye büyük ilerlememizin son adımı. Sadece bir typedef ekleyerek enumumuzu gerçek bir türe dönüştürelim. Ah son şey, typedef'e sınıfınızda izin verilmiyor. Ardından türünüzü hemen yukarıda tanımlayın. Şöyle yapın:

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

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

Etiketin isteğe bağlı olduğunu unutmayın. O zamandan beri, bu durumda, numaralandırıcıları değil, sadece yeni bir tür tanımlamak için etiketliyoruz. O zaman artık buna gerçekten ihtiyacımız yok.

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

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

XCode ile Objective-C geliştiriyorsanız NS_ENUM ön ekine sahip bazı güzel makrolar keşfetmenize izin verir. Bu, iyi numaralandırmaları kolayca tanımlamanıza yardımcı olacaktır ve dahası, statik analizörün derlemeden önce sizin için bazı ilginç kontroller yapmasına yardımcı olacaktır.

İyi Enum!


Her zaman "neden cevaplanmış ve kabul edilmiş bir soruyu neden cevaplarsınız" diye düşündüm. Evlat, her zaman yanılmışım! Bu en iyi cevap ve benim gibi yeni başlayanlara yardımcı oluyor!
rak appdev

10

typedefvarolan bir değişken türünün adını yeniden tanımlamak için kullanışlıdır. Bir veri tipini çağırmak için kısa ve anlamlı bir yol sağlar. Örneğin:

typedef unsigned long int TWOWORDS;

burada, unsigned long int türü TWOWORDS türünde olarak yeniden tanımlanır. Böylece artık imzasız uzun int türünde değişkenler yazarak,

TWOWORDS var1, var2;

onun yerine

unsigned long int var1, var2;

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

o zaman şöyle kullanabilirsiniz: -

 ShapeType shape;

ve

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

şimdi şöyle kullanabilirsiniz: -

enum ShapeType shape;

3

enum, yapı içinde yapılamayan enum öğelerine değer atamak için kullanılır. Bu nedenle, tam değişkene erişmek yerine her zaman enum'daki değişkenlere atadığımız değerle yapabiliriz. Varsayılan olarak 0 atamasıyla başlar, ancak herhangi bir değer atayabiliriz ve enum'daki bir sonraki değişkene önceki değere +1 değeri atanır.


3

Aşağıdaki biçimde kullanabilirsiniz, 0'dan başlayan Raw varsayılan değeri,

  • kCircle 0,
  • kRectangle 1,
  • kOblateSpheroid 2'dir.

Kendi başlangıç ​​değerinizi atayabilirsiniz.

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

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

2

Typedef, programcının bir Objective-C türünü diğeri olarak tanımlamasını sağlar. Örneğin,

typedef int Sayaç; Sayaç türünü int türüne eşdeğer olarak tanımlar. Bu, kod okunabilirliğini büyük ölçüde artırır.


2

Typedef, C ve C ++ 'da bir Anahtar Kelimedir. Temel veri türleri (char, int, float, double, struct & enum) için yeni adlar oluşturmak için kullanılır .

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Burada, numaralandırılmış ShapeType veri türünü oluşturur ve aşağıda verildiği gibi enum Type ShapeType için yeni adlar yazabiliriz

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;

1

enum birçok "hata" türünü azaltabilir ve kodu daha yönetilebilir hale getirebilir

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

Tanımın herhangi bir kısıtlaması yoktur. Bu sadece bir ikame. Devletin tüm koşullarını sınırlayamaz. STATE 5'e atandığında, eşleşen bir durum olmadığından program yanlış olacaktır. Ancak derleyici STATE = 5'i uyarmayacak

Yani böyle kullanmak daha iyidir

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

SampleState state = SampleStateGood;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.