Frage

Ich arbeite mit Objective-C und ich brauche int die von einem NSArray zu einem NSMutableData (Ich bereite ein, die Daten über eine Verbindung zu senden) hinzuzufügen. Wenn ich die int die mit NSNumber wickeln und dann fügen Sie sie zu NSMutableData, wie würde ich herausfinden, wie viele Bytes im NSNumber int sind? Wäre es möglich, sizeof () zu verwenden, da nach der Apfel-Dokumentation „ist NSNumber eine Unterklasse von NSValue, die einen Wert als jeder C Skalar (numerisch) Typ bietet.“?

Beispiel:

NSNumber *numero = [[NSNumber alloc] initWithInt:5];

NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];

[data appendBytes:numero length:sizeof(numero)];
War es hilfreich?

Lösung

numero ist kein numerischer Wert, es ist ein Zeiger auf ein represting einen numerischen Wert ein Objekt ist. Was Sie nicht arbeiten zu tun versuchen, immer die Größe auf einen Zeiger (4 für 32-Bit-Plattformen und 8 für 64-Bit) gleich sein, und Sie werden einigen Müll Zeigerwert auf Ihre Daten anhang in Bezug auf die Anzahl gegenüber.

Auch wenn Sie versuchen würden, dereferenzieren, kann man nicht direkt die Bytes zugreifen einen NSNumber sichern und erwarten, dass es funktioniert. Was ist da los ist ein interne Implementierung Detail und von der Freigabe kann variieren zu lösen, oder sogar zwischen verschiedenen Konfigurationen der gleichen Release (32 Bit vs 64 Bit, iPhone vs Mac OS X, Arm vs i386 vs PPC). Nur die Bytes packen und sie über den Draht zu senden kann in etwas führen, die nicht richtig auf der anderen Seite nicht deserialisieren, auch wenn Sie auf die tatsächlichen Daten erhalten verwaltet.

Sie müssen wirklich mit einer Codierung einer ganzen Zahl kommen Sie in Ihre Daten legen und dann packen und die NSNumbers in das entpacken. So etwas wie:

NSNumber *myNumber = ... //(get a value somehow)
int32_t myInteger = [myNumber integerValue]; //Get the integerValue out of the number
int32_t networkInteger = htonl(myInteger); //Convert the integer to network endian
[data appendBytes:&networkInteger sizeof(networkInteger)]; //stuff it into the data

Auf der Empfangsseite Du dann die ganze Zahl greifen und eine NSNumber mit numberWithInteger neu erstellen. Nach ntohl Verwendung zu nativen Host-Format zu konvertieren

Es kann ein bisschen mehr Arbeit erfordern, wenn Sie minimale Darstellungen zu senden versuchen, etc.

Die andere Option ist eine NSCoder Unterklasse zu verwenden und die NSNumber sagen zu kodieren selbst Ihre Codierer verwenden, da diese Plattform neutral sein, aber es kann zu viel des Guten für das, was Sie zu tun versuchen.

Andere Tipps

Zuerst NSNumber * numero ist "Ein Zeiger auf einen NSNumber Typen", und der NSNumber Typ ein Objective-C Objekt. In der Regel, es sei denn in der Dokumentation ausdrücklich irgendwo erwähnt, die Faustregel, in der Programmierung objektorientiert ist, dass „Die internen Details, wie ein Objekt wählt seinen internen Zustand zu repräsentieren, um die Objekte Implementierung ist privat, und sollte als schwarz behandelt werden Box." Auch hier, es sei denn die Dokumentation sagt, dass Sie nichts anderes tun können, kann man nicht davon ausgehen, dass NSNumber eine C primitive Art von int den int Wert zu speichern verwendet man ihm gegeben hat.

Das folgende ist eine grobe Annäherung an, was hinter den Kulissen "vor sich geht, wenn Sie appendBytes:numero:

typedef struct {
  Class isa;
  double dbl;
  long long ll;
} NSNumber;

NSNumber *numero = malloc(sizeof(NSNumber));
memset(numero, 0, sizeof(NSNumber));
numero->isa = objc_getClass("NSNumber");

void *bytes = malloc(1024);

memcpy(bytes, numero, sizeof(numero)); // sizeof(numero) == sizeof(void *)

Das macht es ein bisschen mehr klar, dass, was Sie mit dem NSMutableData Objekt data sind Anfügen die ersten vier Bytes von dem, was jemals numero zeigt auf (was für ein Objekt in Obj-C ist immer isa, die Objekte der Klasse ). Ich vermute, was Sie „wollte“, war den Zeiger auf das instanzierte Objekt zu tun, kopieren (der Wert von numero), in dem Fall, dass Sie verwendet &numero haben sollte. Dies ist ein Problem, wenn Sie GC verwenden als der Puffer durch NSMutableData verwendet wird, nicht gescannt (dh das GC-System nicht mehr „sehen“ das Objekt und zurückfordern, die zu einem späteren ziemlich eine Garantie für einen zufälligen Absturz Punkt).

Es ist hoffentlich klar, dass selbst wenn Sie sich in NSNumber den Zeiger auf das instanziiert data Objekt setzen, dass Zeiger nur im Rahmen des Prozesses Bedeutung hat, die es erstellt. Ein Zeiger auf dieses Objekt ist noch weniger sinnvoll, wenn Sie diesen Zeiger Senden Sie eine andere der empfangende Computer computer- hat keine (praktisch, trivial) Art und Weise die Erinnerung, dass der Zeiger auf der sendende Computer zu lesen.

Da Sie scheinen Probleme mit diesem Teil des Prozesses zu haben, lassen Sie mich eine Empfehlung aussprechen, dass Sie unzählige Stunden Debuggen einige extrem schwierige Implementierung Bugs sparen Sie verpflichtet sind zulaufen zu:

Abandon

diese ganze Idee zu versuchen, unformatierte Binärdaten zwischen Maschinen zu senden und nur senden einfache ASCII / UTF-8 formatierte Informationen zwischen ihnen.

Wenn Sie denken, dass dies einige, wie langsam oder ineffizient zu gehen, dann lassen Sie mich empfehlen, dass Sie alles, was bringen mit einer vereinfachten ASCII / UTF-8 Zeichenfolge Version zuerst. Vertrauen Sie mir, rohe Binärdaten Debuggen ist kein Spaß, und die Fähigkeit, nur NSLog(@"I got: %@", dataString) ist sein Gewicht in Gold wert, wenn Sie Debuggen unvermeidlichen Probleme. Dann hat einmal alles geliert, und Sie sind sicher, dass Sie keine weiteren Änderungen vornehmen müssen, was es ist Sie austauschen müssen, „Port“ (in Ermangelung eines besseren Wortes), dass die Umsetzung in eine binären nur Version wenn, und nur dann, wenn , mit Shark.app Profilierungs identifiziert es als Problembereich. Als Bezugspunkt kann in diesen Tagen ich eine Datei zwischen Maschinen scp und eine Gigabit-Verbindung mit dem Transfer sättigen. scp hat wahrscheinlich etwa fünftausend Mal zu tun, wie viel Verarbeitung pro Byte zu komprimieren und die Daten als diese einfache stringification alle zu verschlüsseln, während 80 MB / s zu übertragen. Doch auf moderne Hardware ist dies kaum genug, um den CPU-Meter-Lauf in meiner Menüleiste zu bewegen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top