19

I need to transmit an integer through GameKit using sendDataToAllPeers:withDataMode:error: but I don't know how to convert my NSNumber to NSData in order to send. I currently have:

NSNumber *indexNum = [NSNumber numberWithInt:index];
[gkSession sendDataToAllPeers:indexNum withDataMode:GKSendDataReliable error:nil];

but obviously the indexNum needs to be converted to NSData before I can send it. Does anyone know how to do this please?

Thanks!

jowie
  • 8,028
  • 8
  • 55
  • 94

4 Answers4

35

I would not recommend NSKeyedArchiver for such a simple task, because it adds PLIST overhead on top of it and class versioning.

Pack:

NSUInteger index = <some number>;
NSData *payload = [NSData dataWithBytes:&index length:sizeof(index)];

Send:

[session sendDataToAllPeers:payload withDataMode:GKSendDataReliable error:nil];

Unpack (in the GKSession receive handler):

NSUInteger index;
[payload getBytes:&index length:sizeof(index)];

Swift

var i = 123
let data = NSData(bytes: &i, length: sizeof(i.dynamicType))

var i2 = 0
data.getBytes(&i2, length: sizeof(i2.dynamicType))

print(i2) // "123"
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
  • 1
    You assume that the number is a NSUInteger while unpacking. NSNumber can wrap whole lot of different type of numbers - int, float, double, signed / unsigned. I think that archiving and unarchiving is best approach if programmer is not sure what type of data is stored in NSNumber. I go with Ole's approach. – Raj Pawan Gumdal Jan 24 '13 at 09:23
  • Where do you see NSNumber? I never use NSNumber. –  Jan 24 '13 at 10:24
  • The question asked was for NSNumber created from an integer. So, I guess a general solution for NSNumber would have been more appropriate. – Raj Pawan Gumdal Jan 25 '13 at 06:07
  • @Erik Aigner: do you know how to solve this problem with Swift? Thanks in advance! – Sifeng Sep 07 '14 at 20:32
22

To store it:

NSData *numberAsData = [NSKeyedArchiver archivedDataWithRootObject:indexNum];

To convert it back to NSNumber:

NSNumber *indexNum = [NSKeyedUnarchiver unarchiveObjectWithData:numberAsData]; 
Ole Begemann
  • 135,006
  • 31
  • 278
  • 256
  • This should be the accepted answer, as it doesn't assume the number is an integer. – TTillage Feb 08 '16 at 20:44
  • @TTillage Number doesn't have to be an integer for my solution to work. You just have to change the type. –  May 25 '16 at 06:38
  • The answer perfectly matches the title of the question. However @ErikAigner's answer is more specific towards the body of the question. – Ayan Sengupta Dec 21 '19 at 17:52
4

Why not send the integer directly like this:

NSData * indexData = [NSData dataWithBytes:&index length:sizeof(index)];
[gkSession sendDataToAllPeers:indexData withDataMode:GKSendDataReliable error:nil];
Felix
  • 35,354
  • 13
  • 96
  • 143
0

For a more detailed example how to send different payloads you can check the GKRocket example included in the XCode documentation.

HBu
  • 559
  • 6
  • 18