1
votes

my problem is the following. I would like to encapsulate a NSString in a NSMutableData object. But I would like to do it together with other items and without first encapsulating it into a NSData. It's only bytes after all isn't it?

My final NSMutableData object would look something like

[header | stringLength | NSString]

where header is a char and stringLength is an unsigned short. I build my packet like this

unsigned short stringLength = myString.length;
NSMutableData* nData = [NSMutableData dataWithBytes:(const void*)&header length:sizeof(char)];
[nData appendBytes:(const void*)&dataLength length:sizeof(unsigned short)];
[nData appendBytes:(const void*)myString length:stringLength];

I would then send this over a gkSession and at the other end I would extract the sting lenght and then the string itself:

NSString* temp = [NSString alloc];
[data getBytes:(void*)&temp range:NSMakeRange(sizeof(char)+sizeof(unsigned short), stringLenght)];

For some reasons this is giving me bad memory access. I suspect that myString.length is not doing exactly what I would expect. Do you have any hints? Thanks in advance.

1

1 Answers

1
votes

This line is incorrect:

[nData appendBytes:(const void*)myString length:stringLength];

This is encoding the first part of the underlying NSString structure (which is larger than stringLength).

What you mean is:

[nData appendBytes:[myString UTF8String] 
            length:[myString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];

length is the number of characters. This can be substantially smaller than the number of bytes for multibyte characters.

Just as a side note: if you can shorten your length to 1 byte (0-255), then that encoding is called a Pascal String, and CFString can handle that encoding natively (see CFStringGetPascalString()). Not something you generally want to do, but interesting. It's particularly nice with CFStringCreateWithPascalStringNoCopy(), since you can avoid the memory copy operation entirely. This is mostly for legacy support, and I wouldn't jump through any hoops to use it, but sometimes it's handy.