Quelle est la différence entre NSNumber et NSInteger? Y a-t-il plus de primitifs comme ceux-là que je devrais connaître? Y en a-t-il un pour les flotteurs?
Les réponses existantes sont utiles; en y ajoutant:
Oui, NSUInteger
donne deux fois la plage parmi les entiers positifs comme NSInteger
, mais je pense qu'une autre raison essentielle de choisir entre les deux est simplement de distinguer les cas où les valeurs négatives n'ont tout simplement pas de sens .
Exemple: la valeur de retour de la méthode NSArray
de count
est un NSUInteger
, ce qui est logique car nous ne pouvons pas avoir un tableau avec un nombre négatif d'éléments. Lorsque le codeur sait qu'il n'est pas signé, il a plus de liberté pour effectuer des opérations qui pourraient ne pas être fiables dans le cas signé, y compris des opérations au niveau du bit comme le décalage. Ce billet de blog parle plus de signé vs non signé.
Ma conjecture sur CGFloat
vs NSFloat
(qui n'existe pas): Il se pourrait que les concepteurs des éléments de code nommés NeXTSTEP n'avaient tout simplement pas besoin de spécifier trop de valeurs flottantes, en dehors des intervalles de temps. Ils ont donc donné NSTimeInterval
, qui est un type à virgule flottante, mais qui est clairement destiné à être utilisé avec des intervalles de temps. Et, franchement, c'est génial d'avoir ce type parce que vous savez qu'il est toujours censé être en quelques secondes sans avoir à traiter avec une structure. Lorsque vous entrez dans le monde graphique (où réside Core Graphics), des flotteurs sont soudainement autour de vous, planant dans l'air (haha). Il est donc logique d'y introduire un CGFloat
. Ce paragraphe n'est qu'une "spéculation éclairée".
Aussi, juste pour être clair sur pourquoi vous pourriez utiliser NSInteger
etc au lieu des types primitifs : Parce que de cette façon, il est plus facile d'écrire du code portable qui tire pleinement parti de l'architecture de la machine. Par exemple, un CGFloat
utilise 32 bits sur certaines machines et 64 bits sur d'autres, en fonction en grande partie de l'écart d'efficacité qui existe sur ces machines pour ces tailles. Dans certains cas, il n'y a pas de véritable accélération pour utiliser 32 bits contre 64 bits, vous pouvez donc aussi bien utiliser 64 bits. Si vous avez déclaré des choses comme CGFloat
, vous obtenez soudainement cette précision supplémentaire "gratuitement" lorsque vous recompilez.
Et, comme l'a souligné iKenndac, NSNumber
est une classe wrapper pour tous ces derniers (et d'autres types primitifs ou quasi-primitifs comme BOOL
) qui vous permet de l'inclure dans vos NSArray
s et NSDictionary
s, de les archiver plus facilement et de faire d'autres choses que NSObject
s peut faire.
NSNumber
est une classe, pas une primitive, et est utilisé lorsque vous devez mettre des nombres bruts dans des dictionnaires, des tableaux ou les encapsuler autrement. NSInteger
, NSUInteger
, CGFloat
, etc. sont des types simples et correspondent (sur les systèmes 32 bt comme l'iPhone) à int
, unsigned int
et float
.
En règle générale, si vous devez stocker un numéro quelque part, utilisez NSNumber
. Si vous faites des calculs, des boucles, etc., utilisez NSInteger
, NSUInteger
ou CGFloat
.
Vous pouvez encapsuler un NSInteger
dans un NSNumber
:
NSNumber *aNumber = [NSNumber numberWithInteger:21];
... et récupérez-le:
NSInteger anInteger = [aNumber integerValue];
Vous pouvez trouver plus d'informations ici: http://iosdevelopertips.com/cocoa/nsnumber-and-nsinteger.html
NSInteger est comme un int
traditionnel en C. C'est un typedef. Il y en a d'autres comme NSUInteger
, CGFloat
, etc. qui sont tous synonymes de types primitifs.
NSNumber est utile lorsque vous devez coller un nombre dans un NSArray ou NSDictionary. La pratique standard consiste à utiliser ces collections par opposition à la vôtre; l'inconvénient est qu'ils ne peuvent contenir que des objets Objective-C.
NSNumber encapsule essentiellement un int
(ou flottant, etc.) dans un objet Obj-C (similaire au concept de C #/Java de "boxer" un type primitif) qui peut être ajouté à un tableau:
NSArray * myArray = [[NSArray alloc] init];
[myArray addObject:3]; // invalid, will not compile.
[myArray [NSNumber numberWithInt:3]]; // ok
Pour des raisons de performances, si vous le pouvez, utilisez des types primitifs (comme int, float, int []). Cependant, parfois, vous ne pouvez pas éviter NSArray/NSNumber, comme lorsque vous lisez ou écrivez des entrées dans un .plist
fichier.
NSNumber est généralement utilisé pour stocker des variables, NSUInteger est utilisé pour l'arithmétique
vous pouvez changer un NSNumber en NSUInteger en procédant comme suit:
NSNumber *variable = @1;
NSUInteger variableInt = [variable unsignedIntegerValue];
Cela a déjà été dit, mais en règle générale, les variables qui doivent être définies avec * sont des classes Objective C, tandis que les variables qui n'ont pas besoin d'un * sont des primitives C.
Comme d'autres l'ont déjà dit, NSNumber
est une sous-classe NSObject
. Ce n'est pas une primitive C (comme int, unsigned int, float, double, etc.) NSInteger
, CGFloat
, NSUInteger
sont simples typedefs
sur les primitives C.
La nécessité de NSNumber
découle de la nécessité d'utiliser des nombres comme paramètres pour les API qui nécessitent des objets. Par exemple, lorsque vous souhaitez stocker un nombre dans un NSArray
, dans Core-Data ou dans un NSDictionary
.
Y a-t-il plus de primitifs comme ceux-là que je devrais connaître? Eh bien, NSNumber
n'est pas un type primitif, et il enveloppe toutes sortes de nombres (flottants, types entiers, booléens, etc.). Vous devriez également vous renseigner sur NSValue, qui est la base de NSNumber
.
Y en a-t-il un pour les flotteurs? Il n'y a pas de typedef "NS" pour float, mais NSNumber
peut encapsuler n'importe quel nombre float:
NSNumber *myPi = [NSNumber numberWithFloat:3.1415926];
Ou vous pouvez utiliser le type primitif CoreGraphics CGFloat.