2009-08-16 8 views

risposta

50

Le risposte esistenti sono utili; aggiungendo ad essi:

Sì, NSUInteger dà il doppio della portata tra i numeri interi positivi come NSInteger, ma penso che un altro motivo fondamentale per scegliere tra i due è semplicemente di distinguere tra i casi in cui i valori negativi semplicemente non hanno senso.

Esempio: il valore di ritorno del metodo NSArray s' è un countNSUInteger, che ha senso poiché non possiamo avere una matrice con un numero negativo di elementi. Quando il codificatore sa che non è firmato, ha più libertà di eseguire operazioni che potrebbero non essere affidabili nel caso firmato, incluse operazioni bit a bit come lo spostamento. This blog post parla di firmato vs non firmato.

mia ipotesi circa CGFloat vs NSFloat (che non esiste): Potrebbe essere il caso che i progettisti degli elementi di codice NeXTStep-denominati semplicemente non avevano bisogno di specificare troppi valori float, al di fuori del tempo intervalli. Così hanno dato NSTimeInterval, che è un tipo a virgola mobile, ma che è chiaramente inteso per l'uso con intervalli di tempo. E, francamente, è bello avere quel tipo perché sai che è sempre pensato per essere in pochi secondi senza dover affrontare una struttura. Quando ti muovi nel mondo della grafica (dove vive la Core Graphics), improvvisamente fluttua intorno a te, librandosi nell'aria (haha). Quindi ha senso introdurre uno CGFloat lì. Questo paragrafo è tutto "speculazione istruita".

Inoltre, giusto per essere chiari su perché si potrebbe utilizzare NSInteger etc invece di tipi primitivi: Perché in questo modo è più facile scrivere codice portatile che sfrutta appieno l'architettura della macchina. Ad esempio, un CGFloat utilizza 32 bit su alcune macchine e 64 bit su altri, a seconda in gran parte della differenza di efficienza esistente su tali macchine per tali dimensioni. In alcuni casi, non c'è una reale velocità per l'utilizzo di 32 bit contro 64 bit, quindi si potrebbe anche usare 64 bit. Se hai dichiarato le cose come CGFloat, improvvisamente ottieni quella precisione extra "gratis" quando ricompilate.

E, come iKenndac ha sottolineato, NSNumber è una classe wrapper per tutti di questi (e altri tipi primitivi o quasi primitivi come il BOOL) che consente di includere nel vostro NSArray s e NSDictionary s, archiviarli più facilmente e fare altre cose che possono fare NSObject s.

+0

Un punto davvero, davvero poco elegante: NSTimeinterval è un doppio, non un galleggiante. Sono consapevole che il doppio è corto per virgola mobile a precisione doppia, ma comunque. Inoltre, ho capito che la compilazione di CGFloat come una doppia su 64-bit è ottima, ma NSInteger? Non riesco a pensare a una situazione in cui sarebbe utile. Dire in codice che stai facendo alcuni calcoli che hanno bisogno di 64 bit ... non puoi usare NSInteger se lo compili per 32. Se ti piazzi in 32, perché usare 64? Sembra strano. – iKenndac

+1

Hai ragione, NSTimeInterval è un doppio. Penso che conti ancora come un "tipo in virgola mobile", però. Solo con una precisione doppia. Concordo anche sul fatto che in molti casi molti codici non miglioreranno perché NSInteger diventa 64 bit. Ma ecco una possibilità: un generatore di numeri casuali. In questo caso, ti interessa veramente la velocità, quindi potresti voler usare 32 bit quando è più veloce. Ma se 64 bit funzionano altrettanto bene, all'improvviso ottieni un enorme incremento di felicità casuale (lunghezza del ciclo molto più lunga, ecc.) Senza molti (se nessuno) costi di velocità. – Tyler

+0

Perché possiamo votare una sola volta? Brillante! –

56

NSNumber è una classe, non una primitiva e viene utilizzata quando è necessario inserire numeri grezzi in dizionari, array o in altro modo incapsularli. NSInteger, NSUInteger, CGFloat, ecc sono tipi semplici e corrispondono (su sistemi 32-bt come l'iPhone) a int, unsigned int e float.

Come regola generale, se avete bisogno di memorizzare un numero da qualche parte, utilizzare NSNumber. Se stai facendo i calcoli, loop, ecc, utilizzare NSInteger, NSUInteger o CGFloat.

Puoi avvolgere un NSInteger in un NSNumber:

NSNumber *aNumber = [NSNumber numberWithInteger:21]; 

... e tornare indietro:

NSInteger anInteger = [aNumber integerValue]; 

Potete trovare maggiori informazioni qui: http://iosdevelopertips.com/cocoa/nsnumber-and-nsinteger.html

+0

Se il numero non sarà mai negativo, dovrei usare NSUInteger? – mk12

+0

E quale dovrei usare per un numero con un decimale? – mk12

+0

Perché CGFloat e non NSFloat? – mk12

5

NSInteger è proprio come un tradizionale int in C. È un typedef. Ci sono altri come NSUInteger, CGFloat, ecc che tutti sono sinonimi di tipi primitivi.

NSNumber è utile quando è necessario attenersi un numero in un NSArray o NSDictionary. La pratica standard consiste nell'utilizzare queste raccolte rispetto a quelle proprie; lo svantaggio è che possono contenere solo oggetti Objective-C.

NSNumber avvolge essenzialmente un int (o float, ecc) in un oggetto Obj-C (simile al concetto di C#/Java di 'boxe' un tipo primitivo) che può essere aggiunto ad un array:

NSArray * myArray = [[NSArray alloc] init]; 
[myArray addObject:3]; // invalid, will not compile. 
[myArray [NSNumber numberWithInt:3]]; // ok 

Per motivi di prestazioni, se è possibile, utilizzare tipi primitivi (come int, float, int []). Tuttavia, a volte non è possibile evitare NSArray/NSNumber, ad esempio quando si stanno leggendo o scrivendo voci in un file .plist.

+1

NSInteger, NSUInteger e CGFloat sono typedef sicuri sotto 32 o 64 bit. – Abizern

0

Come già detto in precedenza, NSNumber è una sottoclasse NSObject. Non è un primitivo C (come int, unsigned int, float, double, ecc.) NSInteger, CGFloat, NSUInteger sono semplici typedefs sui primitivi C.

La necessità di NSNumber deriva dalla necessità di utilizzare i numeri come parametri per le API che richiedono Oggetti. L'esempio è quando si desidera memorizzare un numero in un NSArray, in Core-Data o in un NSDictionary.

Ci sono più primitivi come questi che dovrei sapere? Bene, NSNumber non è un tipo primitivo, e avvolge tutti i tipi di numeri (float, tipi interi, booleani e così via). Dovresti anche conoscere NSValue, che è la base per NSNumber.

Esiste uno per i galleggianti? Non v'è alcun typedef "NS" per galleggiare, ma NSNumber può avvolgere intorno a qualsiasi numero di float:

NSNumber *myPi = [NSNumber numberWithFloat:3.1415926]; 

Oppure si potrebbe usare i CoreGraphics tipo primitivo CGFloat.

2

NSNumber è generalmente utilizzato per memorizzare le variabili, NSUInteger viene utilizzato per l'aritmetica

è possibile modificare una NSNumber ad un NSUInteger in questo modo:

NSNumber *variable = @1; 
NSUInteger variableInt = [variable unsignedIntegerValue]; 

è stato detto prima, ma in linea di massima di pollice, le variabili che devono essere definite con * sono classi Objective C, mentre le variabili che non hanno bisogno di * sono primitive C.

Problemi correlati