2011-09-14 13 views
36

Qual è la differenza traEnum forme di definizione nella Objective-C

typedef enum { 
    ... 
} Name; 

e

enum { 
    ... 
}; 
typedef NSUInteger Name; 

? Se la funzionalità è la stessa, a cosa serve il secondo modulo? Non è inutilmente disordinato?

+1

il secondo deriva un tipo da NSUInteger, non il primo. –

risposta

84

enum è vecchio come C, quindi una parte di Objective-C. È solo la codifica esplicita di un tipo int. È abbastanza utile per il debug e la maggior parte dei più recenti compilatori possono fare ottimizzazioni basate su di esso. (Che dovresti assolutamente ignorare). È molto utile per rendere il tuo codice più leggibile (a chiunque altro oa te stesso dopo aver dormito).

typedef enum { 
    ... 
} NameType ; 

sarebbe stata seguita da

NameType name; 

e questo è in genere lo stile preferito di un typedef,

tuo secondo esempio sarà non legare il typedef per i valori che si desidera specificare dovrebbe solo essere del tipo dato.

Si noti che questo non impedisce di eseguire

name = 10244; // some non-valid value not listed in the enumeration 

ma alcuni compilatori potrebbe generare un avviso in tal caso,


mi sono imbattuto in uso di Apple di quanto segue oggi:

enum { 
NSFetchedResultsChangeInsert = 1, 
NSFetchedResultsChangeDelete = 2, 
NSFetchedResultsChangeMove = 3, 
NSFetchedResultsChangeUpdate = 4 
}; 
typedef NSUInteger NSFetchedResultsChangeType; 

Lo fanno perché sono veramente desidera che il NSFetchedResultsChangeType sia del tipo definito come NSUInteger.Questo può essere essere un int ma può anche essere qualcos'altro. E con i valori di 1, 2, 3 e 4, è un po 'irrilevante per us di che tipo si tratta. Ma stanno programmando un diverso livello di astrazione perché sono un fornitore di strumenti.

Non si dovrebbe mai guardare ad Apple per i suggerimenti sullo stile di codifica. Se vedi qualcosa che sembra il modo più pulito/migliore di codificare, di solito lo è. Come ha detto Kevin, la stabilità delle API è di fondamentale importanza per loro.


Edit (gennaio 2013) Se si ha accesso alle WWDC 2012 di sessione video, si dovrebbe guardare Session 405 - Modern Objective-C 6: 00-10: 00. È in discussione una nuova sintassi nel compilatore più recente che consente il dimensionamento esplicito di un tipo e il legame stretto dei valori con i tipi. (preso in prestito da C++ 11)

enum NSFetchedResultsChangeType : NSUInteger { 
NSFetchedResultsChangeInsert = 1, 
NSFetchedResultsChangeDelete = 2, 
NSFetchedResultsChangeMove = 3, 
NSFetchedResultsChangeUpdate = 4 
}; 
+0

Sto lavorando per creare la mia libreria di funzioni per iOS proprio ora con l'intento di venderle. Suppongo, quindi, che dovrei andare contro il tuo commento coraggioso e seguire lo stile di Apple? – ArtOfWarfare

+0

@ArtOfWarfare in base all'ampiezza del target la risposta può variare. Se sceglierai come target anche gli ambienti non Apple, i tuoi file di intestazione potrebbero includere tutti i tipi di offuscamento sintattico. Se si sta prendendo di mira solo Apple, la mia opinione sarebbe di non seguire l'esempio di Apple: è la pianificazione a lungo termine. L'unica cosa che ti potrebbe guadagnare è il supporto su qualche ipotetica architettura che nessuno attualmente prevede. Gli altri certamente non saranno d'accordo con me. (a parte: Apple si baserà spesso su architetture di ricerca - un'altra ragione per l'agnosticismo dell'architettura). – bshirley

+0

Grazie per la nota WWDC! –

9

Il primo definisce un nome di tipo per fare riferimento a un enum. Questo è il modo in cui la maggior parte delle enumerazioni è denominata in C. Quest'ultima è un po 'diversa però, ed è diffusa nei framework Cocoa. Ci sono due ragioni per usare quest'ultimo. La prima è se il tuo enum definisce un bitfield, e lo vorrai qui perché quando fornisci un valore "Nome" ti fornirai una combinazione dei valori enum. In altre parole, se si dice qualcosa di simile

[self doSomethingWithBitfield:(Enum1 | Enum2)] 

non sta passando un valore di nome, ma piuttosto un numero intero che è una combinazione dei due.

Tuttavia, i framework Cocoa utilizzano questo idioma anche per valori non bitfield, per una buona ragione: stabilità dell'API. Secondo lo standard C, il tipo integrale sottostante di un enum richiede di essere in grado di contenere tutti i valori nell'enumerazione, ma viene altrimenti scelto dal compilatore. Ciò significa che l'aggiunta di un nuovo valore enum potrebbe modificare il tipo integrale dell'enumerazione (ad esempio l'aggiunta di -1 può farlo firmare, aggiungendo 6 miliardi può renderlo un lungo lungo, ecc.). Questa è una cosa negativa dal punto di vista della stabilità dell'API, perché la codifica dei tipi di metodi che prendono i valori di questa enumerazione potrebbe cambiare in modo imprevisto e potenzialmente interrompere il codice e i file binari esistenti. Per evitare ciò, i framework Cocoa generalmente definiscono il tipo come un NSUInteger (o NSInteger se hanno bisogno di numeri negativi), quindi le codifiche API e type rimangono stabili.

Problemi correlati