Search code examples
objective-cintegerbytensdatansnumber

Does NSNumber add any extra bytes to the number it holds?


I'm working with Objective-C and I need to add int's from a NSArray to a NSMutableData (I'm preparing a to send the data over a connection). If I wrap the int's with NSNumber and then add them to NSMutableData, how would I find out how many bytes are in the NSNumber int? Would it be possible to use sizeof() since according to the apple documentation, "NSNumber is a subclass of NSValue that offers a value as any C scalar (numeric) type."?

Example:

NSNumber *numero = [[NSNumber alloc] initWithInt:5];

NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];

[data appendBytes:numero length:sizeof(numero)];

Solution

  • numero is not a numeric value, it is a pointer to a an object represting a numeric value. What you are trying to do won't work, the size will always be equal to a pointer (4 for 32 bit platforms and 8 for 64 bit), and you will append some garbage pointer value to your data as opposed to the number.

    Even if you were to try to dereference it, you cannot directly access the bytes backing an NSNumber and expect it to work. What is going on is an internal implementation detail, and may vary from release to release, or even between different configurations of the same release (32 bit vs 64 bit, iPhone vs Mac OS X, arm vs i386 vs PPC). Just packing up the bytes and sending them over the wire may result in something that does not deserialize properly on the other side, even if you managed to get to the actual data.

    You really need to come up with an encoding of an integer you can put into your data and then pack and unpack the NSNumbers into that. Something like:

    NSNumber *myNumber = ... //(get a value somehow)
    int32_t myInteger = [myNumber integerValue]; //Get the integerValue out of the number
    int32_t networkInteger = htonl(myInteger); //Convert the integer to network endian
    [data appendBytes:&networkInteger sizeof(networkInteger)]; //stuff it into the data
    

    On the receiving side you then grab out the integer and recreate an NSNumber with numberWithInteger: after using ntohl to convert it to native host format.

    It may require a bit more work if you are trying to send minimal representations, etc.

    The other option is to use an NSCoder subclass and tell the NSNumber to encode itself using your coder, since that will be platform neutral, but it may be overkill for what you are trying to do.