Quand dois-je utiliser NSInteger
vs. int lors du développement pour iOS? Je vois dans l'exemple de code Apple qu'ils utilisent NSInteger
(ou NSUInteger
) lorsqu'ils passent une valeur comme argument à une fonction ou retournent une valeur à partir d'une fonction.
- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...
Mais dans une fonction qu'ils utilisent simplement int
pour suivre une valeur
for (int i; i < something; i++)
...
int something;
something += somethingElseThatsAnInt;
...
J'ai lu (on m'a dit) que NSInteger
c'est un moyen sûr de référencer un entier dans un environnement 64 bits ou 32 bits, alors pourquoi l'utiliser int
?
la source
int
soit mieux adaptée à unlong
. Peut-être savez-vous qu'il ne dépassera pas une certaine plage et pensez donc qu'il sera plus efficace en mémoire à utiliser simplementint
.NSInteger
pour passer des valeurs vers et depuis une API qui le spécifie. En dehors de cela, il n'a aucun avantage sur un int ou un long. Au moins avec un int ou un long, vous savez quels spécificateurs de format utiliser dans un printf ou une instruction similaire.Pourquoi utiliser
int
du tout?Apple utilise
int
car pour une variable de contrôle de boucle (qui n'est utilisée que pour contrôler les itérations de boucle), leint
type de données est correct, à la fois en taille de type de données et en valeurs qu'il peut contenir pour votre boucle. Pas besoin de type de données dépendant de la plateforme ici. Pour une variable de contrôle de boucle, même un 16 bitsint
fera l'affaire la plupart du temps.Apple utilise
NSInteger
pour une valeur de retour de fonction ou pour un argument de fonction parce que dans ce cas, le type de données [taille] est important , parce que ce que vous faites avec une fonction est de communiquer / transmettre des données avec d'autres programmes ou avec d'autres morceaux de code; voir la réponse à Quand dois-je utiliser NSInteger vs int? dans votre question elle-même ...la source
OS X est "LP64". Cela signifie que:
int
est toujours de 32 bits.long long
est toujours 64 bits.NSInteger
etlong
sont toujours de la taille d'un pointeur. Cela signifie qu'ils sont 32 bits sur les systèmes 32 bits et 64 bits sur les systèmes 64 bits.La raison pour laquelle NSInteger existe est parce que de nombreuses API héritées sont utilisées de manière incorrecte
int
au lieu delong
contenir des variables de taille de pointeur, ce qui signifie que les API doivent passer deint
àlong
dans leurs versions 64 bits. En d'autres termes, une API aurait différentes signatures de fonction selon que vous compilez pour des architectures 32 bits ou 64 bits.NSInteger
a l'intention de masquer ce problème avec ces API héritées.Dans votre nouveau code, utilisez
int
si vous avez besoin d'une variable 32 bits,long long
si vous avez besoin d'un entier 64 bits etlong
ouNSInteger
si vous avez besoin d'une variable de la taille d'un pointeur.la source
int32_t
. Si vous avez besoin d'un entier 64 bits, utilisezint64_t
. Si vous avez besoin d'une variable de la taille d'un pointeurintptr_t
.<stdint.h>
types existent à cet effet.LP64
cela ne garantit pas quelong long
c'est 64 bits. UneLP64
plate-forme pourrait choisir d'avoirlong long
un entier de 128 bits.Si vous creusez dans l'implémentation de NSInteger:
Simplement, le typedef NSInteger fait une étape pour vous: si l'architecture est 32 bits, il utilise
int
, s'il est 64 bits, il utiliselong
. En utilisant NSInteger, vous n'avez pas à vous soucier de l'architecture sur laquelle le programme s'exécute.la source
long long
. Ainsi, tous les types numériques utiliseront le même spécificateur de type.NSLog("%@", @(1123));
NSLog("%li", (long)theNSInteger);
Vous devez utiliser NSIntegers si vous devez les comparer à des valeurs constantes telles que NSNotFound ou NSIntegerMax, car ces valeurs différeront sur les systèmes 32 bits et 64 bits, donc indexez les valeurs, les nombres et autres: utilisez NSInteger ou NSUInteger.
Cela ne fait pas de mal d'utiliser NSInteger dans la plupart des cas, sauf qu'il prend deux fois plus de mémoire. L'impact de la mémoire est très faible, mais si vous avez une énorme quantité de nombres flottant à un moment donné, cela peut faire une différence d'utiliser des ints.
Si vous utilisez NSInteger ou NSUInteger, vous souhaiterez les convertir en entiers longs ou en entiers longs non signés lors de l'utilisation de chaînes de format, car la nouvelle fonctionnalité Xcode renvoie un avertissement si vous essayez de vous déconnecter d'un NSInteger comme s'il avait une longueur connue. De même, vous devez être prudent lorsque vous les envoyez à des variables ou des arguments qui sont tapés comme des entiers, car vous risquez de perdre une certaine précision dans le processus.
Dans l'ensemble, si vous ne vous attendez pas à en avoir des centaines de milliers en mémoire à la fois, il est plus facile d'utiliser NSInteger que de vous soucier constamment de la différence entre les deux.
la source
À partir d'aujourd'hui (septembre 2014), je recommanderais d'utiliser
NSInteger/CGFloat
lors de l'interaction avec les API iOS, etc. si vous créez également votre application pour arm64. En effet , vous obtiendrez probablement des résultats inattendus lorsque vous utilisez lesfloat
,long
et lesint
types.EXEMPLE: FLOAT / DOUBLE vs CGFLOAT
Comme exemple, nous prenons la méthode déléguée UITableView
tableView:heightForRowAtIndexPath:
.Dans une application 32 bits uniquement, cela fonctionnera correctement s'il est écrit comme ceci:
float
est une valeur 32 bits et le 44 que vous renvoyez est une valeur 32 bits. Cependant, si nous compilons / exécutons ce même morceau de code dans une architecture arm64 64 bits, le 44 sera une valeur 64 bits. Le renvoi d'une valeur 64 bits lorsqu'une valeur 32 bits est attendue donnera une hauteur de ligne inattendue.Vous pouvez résoudre ce problème en utilisant le
CGFloat
typeCe type représente un 32 bits
float
dans un environnement 32 bits et un 64 bitsdouble
dans un environnement 64 bits. Par conséquent, lorsque vous utilisez ce type, la méthode reçoit toujours le type attendu, quel que soit l'environnement de compilation / d'exécution.Il en va de même pour les méthodes qui attendent des entiers. Ces méthodes attendent une
int
valeur 32 bits dans un environnement 32 bits et une valeur 64 bitslong
dans un environnement 64 bits. Vous pouvez résoudre ce cas en utilisant le typeNSInteger
qui sert deint
oulong
basé sur l'environnement de compilation / exécution.la source
Sur iOS, peu importe si vous utilisez
int
ouNSInteger
. Cela importera plus si / quand iOS passe à 64 bits.En termes simples,
NSInteger
s sontint
s en code 32 bits (et donc 32 bits de long) etlong
s en code 64 bits (long
s en code 64 bits ont une largeur de 64 bits, mais 32 bits en code 32 bits). La raison la plus probable pour utiliserNSInteger
au lieu delong
est de ne pas casser le code 32 bits existant (qui utiliseint
s).CGFloat
a le même problème: sur 32 bits (au moins sur OS X), c'estfloat
; sur 64 bits, c'estdouble
.Mise à jour: avec l'introduction de l'iPhone 5s, de l'iPad Air, de l'iPad Mini avec Retina et d'iOS 7, vous pouvez désormais créer du code 64 bits sur iOS.
Mise à jour 2: En outre, l'utilisation de
NSInteger
s aide à l'interopérabilité du code Swift.la source
int = 4 octets (fixe quelle que soit la taille de l'architecte) NSInteger = dépend de la taille de l'architecte (par exemple pour 4 octets architecte = 4 octets NSInteger taille)
la source