24

I have the following struct:

typedef enum
{
    kPacketTypeJoin = 1,
    kPacketTypeServerAcceptedJoin,
    kPacketTypeSelectedNumber,
} PacketTypes;    
typedef struct
{
    PacketTypes type;
    NSString *name;
} PacketJoin;

how would I convert a PacketJoin into NSData and back to PacketJoin again?

ninjaneer
  • 6,951
  • 8
  • 60
  • 104

1 Answers1

41
// make a NSData object
NSData *myData = [NSData dataWithBytes:&myPacketJoin length:sizeof(myPacketJoin)];

// make a new PacketJoin
PacketJoin newJoin;
[myData getBytes:&newJoin length:sizeof(newJoin)];
Caleb
  • 124,013
  • 19
  • 183
  • 272
  • 2
    It will copy the pointer that's contained in the struct. The NSString object itself is external to the struct and will not be contained in the data. – Chuck Mar 21 '11 at 03:48
  • 2
    @Ninja, if you plan to store/send this data, the NSString won't be sent along, no. You'll just end up with the memory address where the string *was* on the original device. – Jason Coco Mar 21 '11 at 03:48
  • It'll copy the pointer to the string; it won't copy the actual string object, since that's not part of the struct. It won't retain the string, either, so you'd basically be storing a reference to the string without retaining it, which probably isn't a great plan in iOS, where you don't have garbage collection. Is there some reason you're using a struct rather than an object for PacketJoin? Storing an object pointer in a struct seems like asking for trouble. – Caleb Mar 21 '11 at 03:51
  • @Caleb I'm using struct because I am sending this data. @Jason How will I do that? Should I ask a separate question? – ninjaneer Mar 21 '11 at 03:55
  • Then why are you converting it to NSData? In any case, if you're sending this struct, it shouldn't contain pointers. – Caleb Mar 21 '11 at 04:12
  • 3
    You cannot, which is why you shouldn't use NSString for this purpose. You'd need to convert the string to an array of bytes which you can store in the struct. Or, make PacketJoin an object instead of a struct. Then you can implement NSCoding and archive the object to a NSData, which will give you a stream of bytes that you can safely send. [Read this.](http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/Archiving/Archiving.html) – Caleb Mar 21 '11 at 04:58
  • @Caleb Also, is it possible to save a specific part of the enum, say for example in this case the OP only wanted to save `kPacketTypeServerAcceptedJoin` option into the database, is it possible to save only that rather than saving the whole struct? – Pavan Sep 04 '14 at 04:33
  • @Pavan Reading a struct from a `NSData` instance is illustrated in the second part of the code I gave above. Enumerations are just sets of constants, but if you want to save e.g. the `type` field of the `PacketJoin` struct you can certainly do that. Using NSData for what amounts to a simple integer is probably overkill though -- it'd be easier to use `NSNumber` instead. – Caleb Sep 04 '14 at 05:38
  • @Caleb, ok thank you. I just tried to avoid saving an `NSNumber` in the database since it can be seen as arbritrary numbers, on top of that if I change the ordering of my struct then the code would break since I only have the number stored hence the reason for my question. should I be concerned or should I just get on with it and save the number instead and hope no one changes the order of the struct? – Pavan Sep 04 '14 at 05:58