Kiedy używać NSInteger vs. int

Kiedy powinienem używać NSInteger vs. int podczas tworzenia dla iOS? Widzę w przykładowym kodzie Apple ' a, który używa NSInteger (lub NSUInteger) podczas przekazywania wartości jako argumentu do funkcji lub zwracania wartości z funkcji.

- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...

Ale wewnątrz funkcji używają tylko int do śledzenia wartości

for (int i; i < something; i++)
...

int something;
something += somethingElseThatsAnInt;
...

Przeczytałem (powiedziano mi), że NSInteger jest bezpiecznym sposobem odniesienia się do liczby całkowitej w środowisku 64-bitowym lub 32-bitowym, więc po co w ogóle używać int?

Author: Josh Caswell, 2010-12-15

8 answers

Zwykle chcesz używać NSInteger, gdy nie wiesz, na jakiej architekturze procesora może działać Twój kod, więc możesz z jakiegoś powodu chcieć największego możliwego typu int, który w systemach 32-bitowych jest tylko int, podczas gdy w systemie 64-bitowym jest to long.

Zostałbym przy używaniu NSInteger zamiast int/long chyba, że ich potrzebujesz.

NSInteger/NSUInteger są definiowane jako * dynamiczne typedef * s do jednego z tych typów i są definiowane jak to:

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

Jeśli chodzi o odpowiedni specyfikator formatu, którego powinieneś używać dla każdego z tych typów, zobacz sekcję String Programming Guide na temat zależności platformy

 309
Author: Jacob Relkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-30 10:10:10

Po co w ogóle używać int?

Apple używa int ponieważ dla zmiennej sterującej pętlą (która jest używana tylko do kontrolowania iteracji pętli) int typ danych jest w porządku, zarówno w rozmiarze typu danych, jak i w wartościach, które może przechowywać dla pętli. nie ma tu potrzeby stosowania zależnego od platformy typu danych. dla zmiennej sterującej pętlą nawet 16-bitowa int będzie działać przez większość czasu.

Apple używa NSInteger dla wartości zwracanej funkcji lub dla argumentu funkcji , ponieważ w tym przypadku datatype [size] ma znaczenie , ponieważ to, co robisz z Funkcją, to komunikacja / przekazywanie danych z innymi programami lub innymi fragmentami kodu; zobacz odpowiedź na Kiedy powinienem używać NSInteger vs int?W twoim pytaniu...

[Apple] używają NSInteger (lub NSUInteger) podczas przekazywania wartości jako argument do funkcji lub zwracanie wartości {[7] } z funkcji.

 43
Author: Only You,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-08 09:47:29

OS X to "LP64". Oznacza to, że:

int jest zawsze 32-bitowy.

long long jest zawsze 64-bitowy.

NSInteger i long są zawsze wielkości wskaźnika. Oznacza to, że są 32-bitowe w systemach 32-bitowych i 64-bitowych w systemach 64-bitowych.

Powodem istnienia NSInteger jest to, że wiele starszych interfejsów API nieprawidłowo używało int zamiast long do przechowywania zmiennych o rozmiarze wskaźnika, co oznaczało, że interfejsy API musiały zmienić się z int na long w ich 64-bitowych wersjach. Innymi słowy, API będzie miało różne sygnatury funkcji w zależności od tego, czy kompilujesz dla architektur 32-bitowych, czy 64-bitowych. NSInteger zamierza zamaskować ten problem za pomocą starszych interfejsów API.

W nowym kodzie użyj int, jeśli potrzebujesz 32-bitowej zmiennej, long long, jeśli potrzebujesz 64-bitowej liczby całkowitej oraz long lub NSInteger, jeśli potrzebujesz zmiennej o rozmiarze wskaźnika.

 31
Author: Darren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-14 23:50:33

Jeśli zagłębisz się w implementację NSInteger:

#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
#endif

Po prostu typedef NSInteger wykonuje krok za Ciebie: jeśli architektura jest 32-bitowa, używa int, jeśli jest 64-bitowa, używa long. Używając NSInteger, nie musisz się martwić o architekturę, na której działa program.

 25
Author: Evan Mulawski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-14 23:10:24

Powinieneś użyć Nsinteger, 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, zliczania i tym podobne: użyj NSInteger lub NSUInteger.

Nie zaszkodzi używać NSInteger w większości sytuacji, z wyjątkiem tego, że zajmuje dwa razy więcej pamięci. Wpływ pamięci jest bardzo mały, ale jeśli masz ogromną ilość liczb unoszących się w pobliżu w tym samym czasie, może to zrobić różnicę użyj ints.

Jeśli używasz NSInteger lub NSUInteger, będziesz chciał wrzucić je do długich liczb całkowitych lub niepodpisanych długich liczb całkowitych podczas korzystania z ciągów formatowych, ponieważ nowa funkcja Xcode zwraca ostrzeżenie, jeśli spróbujesz wylogować NSInteger tak, jakby miał znaną długość. Podobnie powinieneś być ostrożny przy wysyłaniu ich do zmiennych lub argumentów, które są wpisywane jako ints, ponieważ możesz stracić pewną precyzję w procesie.

Ogólnie, jeśli nie spodziewasz się, że setki tysięcy je w pamięci na raz, łatwiej jest używać NSInteger niż stale martwić się o różnicę między nimi.

 9
Author: Ash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-14 13:00:26

Od chwili obecnej (wrzesień 2014) polecam używanie NSInteger/CGFloat podczas interakcji z API iOS itp., jeśli budujesz również swoją aplikację dla arm64. Dzieje się tak, ponieważ prawdopodobnie otrzymasz nieoczekiwane wyniki, gdy używasz float, long i int typy.

Przykład: FLOAT / DOUBLE vs CGFLOAT

Jako przykład bierzemy metodę delegata UITableView tableView:heightForRowAtIndexPath:.

W aplikacji tylko 32-bitowej będzie działać dobrze, jeśli jest napisany jak to:

-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

float jest wartością 32-bitową, A 44, które zwracasz, jest wartością 32-bitową. Jeśli jednak skompilujemy/uruchomimy ten sam fragment kodu w 64-bitowej architekturze arm64, 44 będzie wartością 64-bitową. Zwracanie wartości 64-bitowej, gdy oczekiwana jest wartość 32-bitowa, spowoduje nieoczekiwaną wysokość wiersza.

Możesz rozwiązać ten problem używając typu CGFloat

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

Ten typ reprezentuje 32-bitowe float w środowisku 32-bitowym i 64-bitowe double w środowisku 64-bitowym. Dlatego przy zastosowaniu tego typu metoda zawsze otrzyma oczekiwany Typ niezależnie od środowiska kompilacji/runtime.

To samo dotyczy metod, które oczekują liczb całkowitych. Takie metody będą oczekiwały wartości 32-bitowej int w środowisku 32-bitowym i 64-bitowej long w środowisku 64-bitowym. Możesz rozwiązać ten problem używając typu NSInteger, który służy jako int lub long w oparciu o środowisko kompilacji/środowiska uruchomieniowego.

 9
Author: Leon Lucardie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 17:02:35

W systemie iOS obecnie nie ma znaczenia, czy używasz int Czy NSInteger. Będzie to miało większe znaczenie, jeśli / Gdy iOS przeniesie się na 64-bity.

Po Prostu, NSIntegerS są intS w kodzie 32-bitowym (a więc 32-bitowym długim) i longS w kodzie 64-bitowym (longS w kodzie 64-bitowym są 64-bitowe, ale 32-bitowe w kodzie 32-bitowym). Najbardziej prawdopodobnym powodem użycia NSInteger zamiast long jest brak złamania istniejącego 32-bitowego kodu (który używa int s).

CGFloat ma ten sam problem: na 32-bitowym (przynajmniej na OS X) jest float; na 64-bit, to double.

Aktualizacja: wraz z wprowadzeniem iPhone 5s, iPad Air, iPad Mini z Retina i iOS 7, możesz teraz zbudować kod 64-bitowy na iOS.

Update 2: również użycie NSInteger S pomaga w interoperacyjności kodu Swift.

 9
Author: MaddTheSane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-28 01:21:54

Int = 4 bajt (stała niezależnie od wielkości architekta) NSInteger = zależy od wielkości architekta (np. dla 4-bajtowego architekta = 4-bajtowy rozmiar NSInteger)

 0
Author: Ankit garg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-17 09:44:21