73

I want to keep NSUInteger into my core data and I don't know which type should I use (integer 16, 32, 64) to suit the space needed.

From my understanding:

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

and NSUInteger is type def of unsigned long which equal to unsigned int (Types in objective-c on iPhone)

so If I convert my NSUInteger to NSNumber with numberWithUnsignedInteger: and save it as NSNumber(Integer 32) I could retrieve my data back safely right?

Cœur
  • 32,421
  • 21
  • 173
  • 232
sarunw
  • 7,448
  • 10
  • 43
  • 76

2 Answers2

12

Do you really need the entire range of an NSUInteger? On iOS that's an unsigned 32 bit value, which can get very large. It will find into a signed 64 bit.

But you probably don't need that much precision anyway. The maximum for a uint32_t is UINT32_MAX which is 4,294,967,295 (4 billion). If you increment once a second, it'll take you more than 136 years to reach that value. Your user's iPhone won't be around by then... :)

Daniel Eggert
  • 6,547
  • 2
  • 23
  • 40
  • 34
    This doesn't really answer the question. How do you know what kind of data he is storing? I've had many instances when I've needed to store a number far larger than 4 billion. – Brandon Oct 06 '14 at 16:13
  • For instance: `var str2 = "small string with large hashValue"` `print(str2.hashValue)` `// 4799450061348893706` – Rich Armstrong Mar 17 '16 at 21:55
  • unhelpful - perhaps he is using an int as a way of storing a state on 32 separate attribute - the 32 one would flip all the bits and make a mess of things – SimonTheDiver Mar 13 '17 at 16:39
8

If at all possible, when writing data to disk or across a network, it's best to be explicit about the size of value. Instead of using NSUInteger as the datatype, use uint16_t, uint32_t, or uint64_t depending on the range you need. This then naturally translates to Integer 16, 32, and 64 in Core Data.

To understand why, consider this scenario:

  1. You opt to use Integer 64 type to store your value.
  2. On a 64-bit iOS device (eg iPhone 6) it stores the value 5,000,000,000.
  3. On a 32-bit iOS device this value is fetched from the store into an NSUInteger (using NSNumber's unsignedIntegerValue).

Now because NSUInteger is only 32-bits on the 32-bit device, the number is no longer 5,000,000,000 because there aren't enough bits to represent 5 billion. If you had swapped the NUInteger in step 3 for uint64_t then the value would still be 5 billion.

If you absolutely must use NSUInteger, then you'll just need to be wary about the issues described above and code defensively for it.

As far as storing unsigned values into the seemingly signed Core Data types, you can safely store them and retrieve them:

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
Ayush Goel
  • 3,086
  • 25
  • 35
ospr
  • 1,630
  • 2
  • 16
  • 21