Разработка для iOS: Как я могу инкапсулировать строку в объект NSData? - PullRequest
0 голосов
/ 08 января 2011

Я создаю многопользовательскую игру на iPhone, и мне нужно отправить строковые данные другим игрокам в игре. Для этого мне нужно каким-то образом инкапсулировать мои строковые данные NSString * в объект NSData. Вот пример того, как структурирован мой код ...

typedef struct 
{
   PACKETTYPE packetType;
   ??? stringToSend;  //<---not sure how to store this
} StringPacket;    

StringPacket msg;
msg.packetType = STRING_PACKET;
msg.stringToSend = ...  //  <---not sure what to do here
NSData *packet = [NSData dataWithBytes:&msg length:sizeof(StringPacket)];

Итак, мой вопрос: если StringPacket является структурой, определенной в моем заголовке, какого типа должно быть свойство stringToSend, чтобы я мог легко вызвать метод dataWithBytes для NSData для инкапсуляции данных пакета объект NSData?

Спасибо за вашу мудрость!

Ответы [ 2 ]

3 голосов
/ 08 января 2011

Сначала вы должны преобразовать вашу NSString в представление UTF8 через [NSString UTF8String].После этого я бы порекомендовал хранить в длину строки пакета, а после этого - сами символы строки.Все, что можно сделать с помощью добавления NSData, созданного из char * через [NSData dataWithBytes:]

NSMutableData packet = [[NSMutableData alloc] init];
[packet appendBytes:&msg.packetType, sizeof(msg.packetType)];
char *str = [yourString UTF8String];
int len = strlen(str);
[packet appendBytes:(void*)&len, sizeof(len)];
[packet appendBytes:(void*)str, len];

Чтобы проанализировать пакет обратно, вы должны сделать:

NSData packet; // your packet
[packet getBytes:(void*)&packet.msg range:NSMakeRange(0, sizeof(packet.msg))];
int len;
[packet getBytes:(void*)&len range:NSMakeRange(sizeof(packet.msg), sizeof(len)];
NSData *strData = [packet subdataWithRange:NSMakeRange(sizeof(packet.msg) + sizeof(len)), packet.length];
NSString *str = [[NSString alloc] initWithData:strData encoding:UTF8Encoding];

Может быть несколькоошибки, так как я пишу по памяти, но я думаю, вы поймете идею.

2 голосов
/ 08 января 2011

Если ваши строки имеют максимальную длину, это довольно просто и может быть сделано эффективно. Итак, предполагая, что максимальная длина строк для этих пакетов составляет 255, и вы решили использовать UTF-8 для кодирования ваших строк (обе стороны должны договориться о том, какую кодировку они используют), вы можете сделать это следующим образом:

typedef struct 
{
   PACKETTYPE packetType;
   uint8_t stringToSend[256];  // UTF8 string with max encoded length of 255 bytes
} StringPacket;    

StringPacket msg;
msg.packetType = STRING_PACKET;
[theString getCString:msg.stringToSend maxLength:256 encoding:NSUTF8StringEncoding];
NSData *packet = [NSData dataWithBytes:&msg length:sizeof(StringPacket)];

Теперь у вас будет правильная строка C в вашем пакете, содержащая не более 255 байтов строковых данных и нулевой терминатор. Обратите внимание: если ваша строка не может быть закодирована в UTF8 в указанном вами размере, метод вернет NO, поэтому ваш реальный код должен проверить это и обработать.

Если у вас нет ограничения по размеру, вы можете делать то же самое, но вам приходится иметь дело с динамическим распределением памяти, копированием байтов, созданием данных и надлежащим освобождением памяти в нужное время, поэтому это становится намного более запутанным, но это та же самая основная идея. См. Также метод -getBytes:maxLength:usedLength:encoding:options:range:remainingRange: для NSString, он может быть очень полезен при генерации этих сообщений, когда размер строки является динамическим и полностью неизвестным.

Однако в самом простом случае приведенный выше код должен выполнить работу.

...