2011-01-08 3 views
0

Ich baue ein Multiplayer-Spiel auf dem iPhone und ich muss String-Daten an die anderen Spieler im Spiel senden. Um dies zu tun, muss ich meine NSString * String-Daten irgendwie in ein NSData-Objekt einkapseln. Hier ist ein Beispiel dafür, wie mein Code strukturiert ...iOS-Entwicklung: Wie kann ich eine Zeichenfolge in einem NSData-Objekt kapseln?

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)]; 

Also meine Frage ist, ob StringPacket eine Struktur in meinem Header definiert ist, welche Art sollte die stringToSend Eigenschaft so sein, dass ich leicht die dataWithBytes Methode aufrufen kann von NSData die Paketdaten in einem NSData-Objekt einzukapseln?

Danke für Ihre Weisheit!

Antwort

3

Zuerst sollten Sie Ihren NSString in UTF8-Darstellung über [NSString UTF8String] konvertieren. Danach würde ich empfehlen, in Packet String-Länge zu speichern, und danach - die String-Zeichen selbst. Alles, was man über das Anhängen NSData getan werden, von char erstellt * via [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]; 

Paket zu analysieren zurück, sollten Sie tun:

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]; 

Es kann einige Fehler sein, da i‘ Ich schreibe aus dem Gedächtnis, aber ich denke, Sie werden die Idee bekommen.

+0

danke, nickolay! Ich bin unklar, was Sie unter "Speichern in Paket String Länge", meinen Sie erstellen eine zusätzliche Eigenschaft, die die Länge der Zeichenfolge speichert? Außerdem ist mir unklar, was Sie meinen, indem Sie die NSData anhängen. Wenn es nicht zu viel Arbeit ist, würde es Ihnen etwas ausmachen, ein schnelles Beispiel zu zeigen? Danke noch einmal! – BeachRunnerFred

+0

Ich habe Änderungen an meinem Post hinzugefügt, um die Formatierung zu verbessern, um die Lesbarkeit zu verbessern. –

+0

Danke, Nickolay, das scheint sehr geradlinig. Eine weitere Frage: Wenn die Daten am anderen Ende eintreffen und ich auf die Daten mit der Methode 'Bytes' der NSData-Klasse zugreife, wie kann ich auf diese einzelnen Byte-Blöcke zugreifen, wenn die String-Länge dynamisch ist? – BeachRunnerFred

2

Wenn Ihre Strings eine maximale Länge haben, ist es ziemlich einfach und kann effizient durchgeführt werden. Angenommen, die maximale Länge der Zeichenfolgen für diese Pakete ist 255 und Sie haben entschieden, UTF-8 zu verwenden, um Ihre Zeichenfolgen zu kodieren (beide Seiten müssen sich über die verwendete Kodierung einigen), können Sie Folgendes tun:

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)]; 

Jetzt haben Sie eine richtige C-Zeichenfolge in Ihrem Paket, die maximal 255 Byte Zeichenfolgedaten und den Nullabschlusszeichen hat. Hinweis: Wenn Ihre Zeichenfolge nicht in UTF8 in der Größe kodiert werden kann, die Sie angegeben haben, gibt die Methode NO zurück, sodass Ihr tatsächlicher Code dies überprüfen und verarbeiten sollte.

Wenn Sie keine Größenbeschränkung haben, können Sie grundsätzlich das Gleiche tun, aber Sie müssen sich damit beschäftigen, den Speicher dynamisch zuzuweisen, die Bytes zu kopieren, die Daten zu erstellen und den Speicher zur richtigen Zeit freizugeben. so wird es viel mehr beteiligt, aber es ist die gleiche Grundidee. Siehe auch die Methode -getBytes:maxLength:usedLength:encoding:options:range:remainingRange: auf NSString, kann es sehr nützlich sein, diese Nachrichten zu generieren, wo die String-Größe dynamisch und völlig unbekannt ist.

Für den einfachsten Fall sollte jedoch der obige Code die Arbeit erledigen.

+0

Vielen Dank, Jason! – BeachRunnerFred

+0

Dies berücksichtigt nicht unterschiedliche String-Länge, daher wird für kürzere Strings ein Overhead gesendet, und für längere Strings werden sie abgeschnitten. –

+0

@Nickolay: Ja, es wird definitiv seine 256 Bytes jedes Mal senden, aber wie ich bereits sagte, wird es nicht die Zeichenfolge abgeschnitten, es wird den Aufruf vollständig fehlschlagen und Sie müssten dafür überprüfen. –

Verwandte Themen