Wann sollte ich NSInteger
vs. int bei der Entwicklung für iOS verwenden? Ich sehe im Apple-Beispielcode, dass sie NSInteger
(oder NSUInteger
) verwenden, wenn sie einen Wert als Argument an eine Funktion übergeben oder einen Wert von einer Funktion zurückgeben.
- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...
Aber innerhalb einer Funktion verwenden sie nur, int
um einen Wert zu verfolgen
for (int i; i < something; i++)
...
int something;
something += somethingElseThatsAnInt;
...
Ich habe gelesen (wurde mir gesagt), dass dies NSInteger
eine sichere Möglichkeit ist, eine Ganzzahl in einer 64-Bit- oder 32-Bit-Umgebung zu referenzieren. Warum also int
überhaupt verwenden?
quelle
int
von a sogar für a besser geeignet istlong
. Vielleicht wissen Sie, dass es einen bestimmten Bereich nicht überschreitet, und denken daher, dass es speichereffizienter ist, es einfach zu verwendenint
.NSInteger
ist die Übergabe von Werten an und von einer API, die dies angibt. Davon abgesehen hat es keinen Vorteil gegenüber einem int oder einem long. Zumindest mit einem int oder einem long wissen Sie, welche Formatspezifizierer in einer printf- oder ähnlichen Anweisung verwendet werden sollen.Warum
int
überhaupt verwenden?Apple verwendet,
int
weil für eine Schleifensteuervariable (die nur zur Steuerung der Schleifeniterationen verwendet wird) derint
Datentyp in Ordnung ist, sowohl in Bezug auf die Datentypgröße als auch in Bezug auf die Werte, die er für Ihre Schleife enthalten kann. Hier ist kein plattformabhängiger Datentyp erforderlich. Bei einer Regelkreisvariablen reichtint
meistens sogar ein 16-Bit aus.Apple verwendet
NSInteger
für einen Funktionsrückgabewert oder für ein Funktionsargument, da in diesem Fall der Datentyp [Größe] wichtig ist , weil Sie mit einer Funktion Daten mit anderen Programmen oder mit anderen Codeteilen kommunizieren / übergeben. Siehe die Antwort auf Wann sollte ich NSInteger vs int verwenden? in deiner Frage selbst ...quelle
OS X ist "LP64". Das bedeutet, dass:
int
ist immer 32-Bit.long long
ist immer 64-Bit.NSInteger
undlong
sind immer zeigergroß. Das heißt, sie sind 32-Bit auf 32-Bit-Systemen und 64-Bit auf 64-Bit-Systemen.Der Grund, warum NSInteger vorhanden ist, liegt darin, dass viele ältere APIs fälschlicherweise verwendet wurden,
int
anstattlong
Variablen in Zeigergröße zu speichern , was bedeutete, dass die APIs in ihren 64-Bit-Versionen vonint
auf geändert werden musstenlong
. Mit anderen Worten, eine API hat unterschiedliche Funktionssignaturen, je nachdem, ob Sie für 32-Bit- oder 64-Bit-Architekturen kompilieren.NSInteger
beabsichtigt, dieses Problem mit diesen Legacy-APIs zu maskieren.Verwenden
int
Sie in Ihrem neuen Code, wenn Sie eine 32-Bit-Variablelong long
benötigen , wenn Sie eine 64-Bit-Ganzzahl benötigenlong
oderNSInteger
wenn Sie eine Variable in Zeigergröße benötigen.quelle
int32_t
. Wenn Sie eine 64-Bit-Ganzzahl benötigen, verwenden Sieint64_t
. Wenn Sie eine Variable in Zeigergröße benötigen, verwenden Sieintptr_t
.<stdint.h>
Typen existieren zu diesem Zweck.LP64
dies keine Garantielong long
für 64 Bit ist. EineLP64
Plattform könnte sichlong long
für eine 128-Bit-Ganzzahl entscheiden.Wenn Sie sich mit der Implementierung von NSInteger befassen:
Das NSInteger-Typedef erledigt einfach einen Schritt für Sie: Wenn die Architektur 32-Bit ist, wird es verwendet
int
, wenn es 64-Bit ist, wird es verwendetlong
. Mit NSInteger müssen Sie sich keine Gedanken über die Architektur machen, auf der das Programm ausgeführt wird.quelle
long long
. Daher verwenden alle numerischen Typen denselben Typbezeichner.NSLog("%@", @(1123));
NSLog("%li", (long)theNSInteger);
Sie sollten NSInteger verwenden, wenn Sie sie mit konstanten Werten wie NSNotFound oder NSIntegerMax vergleichen müssen, da sich diese Werte auf 32-Bit- und 64-Bit-Systemen unterscheiden. Verwenden Sie daher Indexwerte, Anzahl und dergleichen: Verwenden Sie NSInteger oder NSUInteger.
Es tut in den meisten Fällen nicht weh, NSInteger zu verwenden, außer dass es doppelt so viel Speicher beansprucht. Die Auswirkungen auf den Speicher sind sehr gering. Wenn jedoch eine große Anzahl von Zahlen gleichzeitig im Umlauf ist, kann die Verwendung von Ints einen Unterschied machen.
Wenn Sie NSInteger oder NSUInteger verwenden, möchten Sie diese bei Verwendung von Formatzeichenfolgen in lange Ganzzahlen oder vorzeichenlose lange Ganzzahlen umwandeln, da die neue Xcode-Funktion eine Warnung zurückgibt, wenn Sie versuchen, eine NSInteger abzumelden, als ob sie eine bekannte Länge hätte. Sie sollten ebenfalls vorsichtig sein, wenn Sie sie an Variablen oder Argumente senden, die als Ints eingegeben werden, da Sie dabei möglicherweise an Genauigkeit verlieren.
Im Großen und Ganzen ist es einfacher, NSInteger zu verwenden, wenn Sie nicht erwarten, Hunderttausende von ihnen gleichzeitig im Speicher zu haben, als sich ständig um den Unterschied zwischen den beiden zu sorgen.
quelle
Ab sofort (September 2014) würde ich die Verwendung empfehlen
NSInteger/CGFloat
sofort bei der Interaktion mit iOS-APIs usw. wenn Sie Ihre App auch für arm64 erstellen. Dies liegt daran , dass Sie wahrscheinlich unerwartete Ergebnisse erhalten, wenn Sie verwenden , um diefloat
,long
undint
Typen.BEISPIEL: FLOAT / DOUBLE vs CGFLOAT
Als Beispiel nehmen wir die UITableView-Delegatenmethode
tableView:heightForRowAtIndexPath:
.In einer 32-Bit-Anwendung funktioniert es einwandfrei, wenn es wie folgt geschrieben ist:
float
ist ein 32-Bit-Wert und die 44, die Sie zurückgeben, ist ein 32-Bit-Wert. Wenn wir jedoch denselben Code in einer 64-Bit-arm64-Architektur kompilieren / ausführen, ist 44 ein 64-Bit-Wert. Die Rückgabe eines 64-Bit-Werts, wenn ein 32-Bit-Wert erwartet wird, führt zu einer unerwarteten Zeilenhöhe.Sie können dieses Problem mithilfe des
CGFloat
Typs lösenDieser Typ repräsentiert ein 32-Bit
float
in einer 32-Bit-Umgebung und ein 64-Bitdouble
in einer 64-Bit-Umgebung. Daher erhält die Methode bei Verwendung dieses Typs unabhängig von der Kompilierungs- / Laufzeitumgebung immer den erwarteten Typ.Gleiches gilt für Methoden, die Ganzzahlen erwarten. Solche Methoden erwarten einen 32-Bit-
int
Wert in einer 32-Bit-Umgebung und einen 64-Bit - Wertlong
in einer 64-Bit-Umgebung. Sie können diesen Fall lösen, indem Sie den Typ verwendenNSInteger
, der alsint
oderlong
basierend auf der Kompilierungs- / Laufzeitumgebung dient.quelle
Unter iOS spielt es derzeit keine Rolle, ob Sie
int
oder verwendenNSInteger
. Es ist wichtiger, wenn iOS auf 64-Bit umstellt.Einfach ausgedrückt,
NSInteger
s sindint
s in 32-Bit-Code (und damit 32-Bit lang) undlong
s in 64-Bit-Code (long
s in 64-Bit-Code sind 64-Bit breit, aber 32-Bit in 32-Bit-Code). Der wahrscheinlichste Grund für die VerwendungNSInteger
anstelle vonlong
ist, vorhandenen 32-Bit-Code (derint
s verwendet) nicht zu beschädigen .CGFloat
hat das gleiche Problem: unter 32-Bit (zumindest unter OS X) ist esfloat
; auf 64-Bit ist esdouble
.Update: Mit der Einführung des iPhone 5s, iPad Air, iPad Mini mit Retina und iOS 7 können Sie jetzt 64-Bit-Code unter iOS erstellen.
Update 2: Die Verwendung von
NSInteger
s hilft auch bei der Interoperabilität von Swift-Code.quelle
int = 4 Byte (fest, unabhängig von der Größe des Architekten) NSInteger = abhängig von der Größe des Architekten (z. B. für 4 Byte Architekt = 4 Byte NSInteger-Größe)
quelle