web-dev-qa-db-fra.com

Quel NSNumber (Integer 16, 32, 64) dans Core Data dois-je utiliser pour conserver NSUInteger

Je veux conserver NSUInteger dans mes données de base et je ne sais pas quel type dois-je utiliser (entier 16, 32, 64) pour convenir à l'espace nécessaire.

De ma compréhension:

Integer 16 can have minimum value of -32,768 to 32,767
Integer 32 can have minimum value of -2,147,483,648 to 2,147,483,647
Integer 64 can have minimum value of -very large to very large

et NSUInteger est le type def de unsigned long qui est égal à unsigned int ( Types dans objective-c sur iPhone )

donc si je convertis mon NSUInteger en NSNumber avec numberWithUnsignedInteger: et l'enregistre en tant que NSNumber (entier 32), je pourrais récupérer mes données en toute sécurité, n'est-ce pas?

66
sarunw

Avez-vous vraiment besoin de toute la gamme d'un NSUInteger? Sur iOS, il s'agit d'une valeur 32 bits non signée, qui peut devenir très importante. Il trouvera dans un 64 bits signé.

Mais vous n'avez probablement pas besoin de beaucoup de précision de toute façon. Le maximum pour un uint32_t est UINT32_MAX, soit 4 294 967 295 (4 milliards). Si vous augmentez une fois par seconde, il vous faudra plus de 136 ans pour atteindre cette valeur. L'iPhone de votre utilisateur ne sera pas là d'ici là ... :)

13
Daniel Eggert

Si possible, lors de l'écriture de données sur le disque ou sur un réseau, il est préférable d'être explicite sur la taille de la valeur. Au lieu d'utiliser NSUInteger comme type de données, utilisez uint16_t, uint32_t, ou uint64_t selon la gamme dont vous avez besoin. Cela se traduit alors naturellement par Integer 16, 32 et 64 dans Core Data.

Pour comprendre pourquoi, envisagez ce scénario:

  1. Vous choisissez d'utiliser le type Integer 64 pour stocker votre valeur.
  2. Sur un appareil iOS 64 bits (par exemple iPhone 6), il stocke la valeur 5 000 000 000.
  3. Sur un appareil iOS 32 bits, cette valeur est extraite du magasin dans un NSUInteger (en utilisant unsignedIntegerValue de NSNumber).

Maintenant que NSUInteger n'est que de 32 bits sur le périphérique 32 bits, le nombre n'est plus de 5 000 000 000 car il n'y a pas assez de bits pour représenter 5 milliards. Si vous avez échangé le NUInteger à l'étape 3 pour uint64_t alors la valeur serait encore de 5 milliards.

Si vous devez absolument utiliser NSUInteger, alors vous devrez simplement vous méfier des problèmes décrits ci-dessus et coder de manière défensive pour cela.

En ce qui concerne le stockage de valeurs non signées dans les types de données de base apparemment signés, vous pouvez les stocker en toute sécurité et les récupérer:

NSManagedObject *object = // create object
object.valueNumber = @(4000000000); // Store 4 billion in an Integer 32 Core Data type
[managedObjectContext save:NULL] // Save value to store

// Later on
NSManagedObject *object = // fetch object from store
uint32_t value = object.valueNumber.unsignedIntegerValue; // value will be 4 billion
8
ospr