Obj-C How to convert NSData to an array of ints?

10,163

Solution 1

You can use the functions defined in OSByteOrder.h to deal with endianness. Aside from that quirk, this is really just a matter of grabbing the byte buffer and iterating over it.

// returns an NSArray containing NSNumbers from an NSData
// the NSData contains a series of 32-bit little-endian ints
NSArray *arrayFromData(NSData *data) {
    void *bytes = [data bytes];
    NSMutableArray *ary = [NSMutableArray array];
    for (NSUInteger i = 0; i < [data length]; i += sizeof(int32_t)) {
        int32_t elem = OSReadLittleInt32(bytes, i);
        [ary addObject:[NSNumber numberWithInt:elem]];
    }
    return ary;
}

Solution 2

Sounds like there are cleaner ways to do what you're trying to do, but this should work:

NSData *data = ...; // Initialized earlier
int *values = [data bytes], cnt = [data length]/sizeof(int);
for (int i = 0; i < cnt; ++i)
  NSLog(@"%d\n", values[i]);

Solution 3

This answer is very similar to other answers above, but I found it instructive to play with casting the NSData bytes back to an int32_t[] array. This code works correctly on a little-endian processor (x64 in my case) but would be silently wrong on big-endian (PPC) because the byte representation would be big-endian.

int32_t raw_data[] = {0,1,2,3,4,5,6,7,8,9,10};
printf("raw_data has %d elements\n", sizeof(raw_data)/sizeof(*raw_data));
NSData *data = [NSData dataWithBytes:(void*)raw_data length:sizeof(raw_data)];
printf("data has %d bytes\n", [data length]);
int32_t *int_data_out = (int32_t*) [data bytes];
for (int i=0; i<[data length]/4; ++i)
    printf("int %d = %d\n", i, int_data_out[i]);
[data release];
Share:
10,163
Justin808
Author by

Justin808

Just some guy on the interwebs.

Updated on July 24, 2022

Comments

  • Justin808
    Justin808 almost 2 years

    I have a NSData item that is holding a bunch of ints. How do I go about getting them out and into an NSArray?

    The memory structure in the NSData is 32-bit int in little-endian order, one right after the other.

    Sorry for the basic question, but still learning the obj-c way of doing things :)

  • Lily Ballard
    Lily Ballard about 13 years
    I think int is still 4 bytes long on x86_64. It's long that matches the word size. Or more specifically, int is compiler-dependent, but in gcc and clang on all architectures Cocoa supports, it will be 4 bytes. Still, int32_t would be more appropriate (and you can see what's what I used in my answer).
  • John
    John about 13 years
    I wrote the code on x86_64 - int is still 4 bytes long. But you are both right, int32_t is more appropriate.
  • Nils Ziehn
    Nils Ziehn over 9 years
    NSInteger is the one that changes for x86_64
  • Żabojad
    Żabojad over 5 years
    the line 2 of you proposition gives a warning: Initializing 'int *' with an expression of type 'const void *' discards qualifiers. What does it mean?