Kiedy powinienem używać NSInteger
kontra int przy programowaniu na iOS? Widzę w przykładowym kodzie Apple, którego używają NSInteger
(lub NSUInteger
), gdy przekazują wartość jako argument do funkcji lub zwracają wartość z funkcji.
- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...
Ale w ramach funkcji służą int
do śledzenia wartości
for (int i; i < something; i++)
...
int something;
something += somethingElseThatsAnInt;
...
Przeczytałem (powiedziano), że NSInteger
jest to bezpieczny sposób na odwołanie się do liczby całkowitej w środowisku 64-bitowym lub 32-bitowym, więc po int
co w ogóle korzystać?
źródło
int
byłoby lepiej dostosowane nawet dolong
. Być może wiesz, że nie przekroczy pewnego zakresu i dlatego uważasz, że po prostu będzie bardziej wydajne pod względem pamięciint
.NSInteger
to przekazywanie wartości do iz interfejsu API, który to określa. Poza tym nie ma przewagi nad intem ani długim. Przynajmniej int lub długi wiesz, jakich specyfikatorów formatu należy użyć w instrukcji printf lub podobnej.Po
int
co w ogóle korzystać?Apple używa,
int
ponieważ dla zmiennej sterującej pętli (która służy tylko do sterowania iteracjami pętli)int
typ danych jest w porządku, zarówno pod względem wielkości typu danych, jak i wartości, które może przechowywać dla twojej pętli. Nie ma potrzeby tutaj typu danych zależnego od platformy. Dla zmiennej kontrolnej pętli nawet 16-bitowejint
będzie wystarczająca.Apple używa
NSInteger
wartości zwracanej przez funkcję lub argumentu funkcji, ponieważ w tym przypadku typ danych [rozmiar] ma znaczenie , ponieważ to, co robisz z funkcją, to komunikowanie / przekazywanie danych z innymi programami lub innymi fragmentami kodu; zobacz odpowiedź na pytanie Kiedy powinienem używać NSInteger vs int? w twoim pytaniu ...źródło
OS X to „LP64”. To znaczy że:
int
jest zawsze 32-bitowy.long long
jest zawsze 64-bitowy.NSInteger
ilong
zawsze mają rozmiar wskaźnika. Oznacza to, że mają 32 bity w systemach 32-bitowych i 64 bity w systemach 64-bitowych.Powodem istnienia NSInteger jest niepoprawne użycie wielu starszych interfejsów API
int
zamiastlong
przechowywania zmiennych wielkości wskaźnika, co oznaczało, że interfejsy API musiały zmienić się zint
nalong
64-bitowe wersje. Innymi słowy, interfejs API miałby różne sygnatury funkcji w zależności od tego, czy kompilujesz dla architektury 32-bitowej, czy 64-bitowej.NSInteger
zamierza maskować ten problem za pomocą tych starszych interfejsów API.W nowym kodzie użyj,
int
jeśli potrzebujesz zmiennej 32-bitowej,long long
jeśli potrzebujesz 64-bitowej liczby całkowitej,long
lubNSInteger
jeśli potrzebujesz zmiennej wielkości wskaźnika.źródło
int32_t
. Jeśli potrzebujesz 64-bitowej liczby całkowitejint64_t
. Jeśli potrzebujesz zmiennej wielkości wskaźnika, użyjintptr_t
.<stdint.h>
typy istnieją do tego celu.LP64
nie gwarantujelong long
to 64 bitów.LP64
Platforma mogła zdecydować sięlong long
być 128 bitową liczbą całkowitą.Jeśli zagłębisz się w implementację NSInteger:
Po prostu typedef NSInteger robi krok za Tobą: jeśli architektura jest 32-bitowa, używa
int
, jeśli jest 64-bitowa, używalong
. Korzystając z NSInteger, nie musisz się martwić architekturą, na której działa program.źródło
long long
. Dlatego wszystkie typy liczbowe będą używać tego samego specyfikatora typów.NSLog("%@", @(1123));
NSLog("%li", (long)theNSInteger);
Powinieneś użyć NSIntegers, jeśli chcesz porównać je ze stałymi wartościami, takimi jak NSNotFound lub NSIntegerMax, ponieważ wartości te będą się różnić w systemach 32-bitowych i 64-bitowych, więc wartości indeksu, liczby i tym podobne: użyj NSInteger lub NSUInteger.
Używanie NSInteger w większości przypadków nie zaszkodzi, z wyjątkiem tego, że zajmuje dwa razy więcej pamięci. Wpływ na pamięć jest bardzo niewielki, ale jeśli w danym momencie unosi się ogromna liczba liczb, użycie ints może mieć znaczenie.
Jeśli używasz NSInteger lub NSUInteger, będziesz chciał rzutować je na długie liczby całkowite lub niepodpisane długie liczby całkowite podczas korzystania z ciągów formatujących, ponieważ nowa funkcja Xcode zwraca ostrzeżenie, jeśli spróbujesz wylogować się z NSInteger, jakby miał znaną długość. Podobnie powinieneś zachować ostrożność, wysyłając je do zmiennych lub argumentów wpisanych jako ints, ponieważ możesz stracić trochę precyzji w procesie.
Ogólnie rzecz biorąc, jeśli nie spodziewasz się, że w pamięci będą znajdować się setki tysięcy z nich, łatwiej jest używać NSInteger, niż stale martwić się różnicą między nimi.
źródło
Na dzień dzisiejszy (wrzesień 2014 r.) Zalecam używanie
NSInteger/CGFloat
podczas interakcji z interfejsami API iOS itp., Jeśli budujesz również swoją aplikację dla arm64. Wynika to z faktu, że prawdopodobnie uzyskasz nieoczekiwane wyniki podczas korzystania zfloat
,long
iint
typy.PRZYKŁAD: FLOAT / DOUBLE vs CGFLOAT
Jako przykład bierzemy metodę delegowania UITableView
tableView:heightForRowAtIndexPath:
.W aplikacji tylko 32-bitowej będzie działać poprawnie, jeśli zostanie napisany w następujący sposób:
float
jest wartością 32-bitową, a zwracana wartość 44 jest wartością 32-bitową. Jeśli jednak skompilujemy / uruchomimy ten sam fragment kodu w 64-bitowej architekturze arm64, wartość 44 będzie wartością 64-bitową. Zwrócenie wartości 64-bitowej, gdy oczekiwana jest wartość 32-bitowa, da nieoczekiwaną wysokość wiersza.Możesz rozwiązać ten problem, używając
CGFloat
typuTen typ reprezentuje 32-bit
float
w środowisku 32-bitowym i 64-bitdouble
w środowisku 64-bitowym. Dlatego podczas korzystania z tego typu metoda zawsze otrzyma oczekiwany typ niezależnie od środowiska kompilacji / środowiska wykonawczego.To samo dotyczy metod, które oczekują liczb całkowitych. Takie metody będą oczekiwać
int
wartości 32-bitowej w środowisku 32-bitowym i 64-bitowejlong
w środowisku 64-bitowym. Można rozwiązać ten przypadek za pomocą typNSInteger
, który służy jakoint
lublong
na podstawie kompilacji / Runtime environemnt.źródło
W systemie iOS obecnie nie ma znaczenia, czy używasz
int
lubNSInteger
. Będzie to miało większe znaczenie, jeśli / kiedy iOS przejdzie na 64-bit.Mówiąc najprościej,
NSInteger
s sąint
w kodzie 32-bitowym (a zatem 32-bitowym) ilong
s są w kodzie 64-bitowym (long
s w kodzie 64-bitowym mają szerokość 64-bitową, ale 32-bit w kodzie 32-bitowym). Najbardziej prawdopodobnym powodem użyciaNSInteger
zamiastlong
nie jest łamanie istniejącego 32-bitowego kodu (który używaint
s).CGFloat
ma ten sam problem: w wersji 32-bitowej (przynajmniej w OS X) jestfloat
; w wersji 64-bitowejdouble
.Aktualizacja: Wraz z wprowadzeniem iPhone'a 5s, iPada Air, iPada Mini z Retiną i iOS 7 możesz teraz budować 64-bitowy kod na iOS.
Aktualizacja 2: Ponadto użycie
NSInteger
s pomaga we współdziałaniu kodu Swift.źródło
int = 4 bajty (ustalony niezależnie od wielkości architekta) NSInteger = zależy od wielkości architekta (np. dla 4 bajtów architekta = 4 bajty wielkości NSInteger)
źródło