Когда использовать NSInteger против int
когда я должен использовать NSInteger
и int при разработке для iOS? Я вижу в образце кода Apple, который они используют NSInteger
(или NSUInteger
) при передаче значения в качестве аргумента функции или при возврате значения из функции.
- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...
но внутри функции, они просто используя int
для отслеживания значения
for (int i; i < something; i++)
...
int something;
something += somethingElseThatsAnInt;
...
Я читал (мне сказали), что NSInteger
- безопасный способ ссылаться на целое число в 64-разрядной или 32-разрядной среде, поэтому зачем использовать int
at все?
8 ответов
вы обычно хотите использовать NSInteger
когда вы не знаете, на какой архитектуре процессора может работать ваш код, поэтому вы можете по какой-то причине хотеть максимально возможного int
тип, который в 32-битных системах является просто int
, в то время как на 64-битной системе это long
.
Я бы придерживался использования NSInteger
вместо int
/long
если вы специально не требовать их.
NSInteger
/NSUInteger
определяются как * dynamic typedef
* s к одному из этих типов, и они определяются следующим образом:
#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
что касается правильного спецификатора формата, который вы должны использовать для каждого из этих типов, см. раздел руководства по строковому программированию на зависимостях платформы
зачем использовать int
на всех?
Apple использует int
потому что для переменной управления циклом (которая используется только для управления итерациями цикла)int
DataType-это хорошо, в размер типа данных и значений он может держать за петлю. здесь нет необходимости в зависимом от платформы типе данных. для переменной управления циклом даже 16-бит int
будет делать большую часть времени.
Apple использует NSInteger
функции возвращаемое значение для функции аргумент потому что в этом случае тип данных [размер] имеет значение, потому что то, что вы делаете с функцией, передает/передает данные с другими программами или с другими частями кода; см. ответ на когда я должен использовать NSInteger против int? в самом вашем вопросе...
они [Apple] используют NSInteger (или NSUInteger) при передаче значения как аргумент функции или возвращает значение из a функция.
OS X - это "LP64". Это означает, что:
int
всегда 32-бит.
long long
всегда 64-бит.
NSInteger
и long
всегда имеют размер указателя. Это означает, что они 32-разрядные в 32-разрядных системах и 64-разрядные в 64-разрядных системах.
причина существования NSInteger заключается в том, что многие устаревшие API неправильно используются int
вместо long
для хранения переменных размером с указатель, что означало, что API должен был измениться с int
to long
в их 64-битные версии. Другими словами, API может иметь разные сигнатуры функций в зависимости от компиляции для 32-разрядных или 64-разрядных архитектур. NSInteger
намеревается замаскировать эту проблему с помощью этих устаревших API.
в новом коде используйте int
Если вам нужна 32-битная переменная, long long
Если вам нужно 64-разрядное целое число и long
или NSInteger
Если вам нужна переменная размером с указатель.
Если вы копаетесь в реализации NSInteger:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
#endif
просто, nsinteger typedef делает шаг для вас: если архитектура 32-разрядная, она использует int
, если он 64-разрядный, он использует long
. Используя NSInteger, вам не нужно беспокоиться об архитектуре, на которой работает программа.
вы должны использовать NSIntegers, если вам нужно сравнить их с постоянными значениями, такими как NSNotFound или NSIntegerMax, поскольку эти значения будут отличаться в 32-разрядных и 64-разрядных системах, поэтому значения Индекса, счетчики и тому подобное: используйте NSInteger или NSUInteger.
в большинстве случаев не помешает использовать NSInteger, за исключением того, что он занимает вдвое больше памяти. Влияние памяти очень мало, но если у вас есть огромное количество чисел, плавающих вокруг в любой момент времени, это может сделать разница в использовании ИНЦ.
Если вы используете NSInteger или NSUInteger, вы захотите разбить их на длинные целые или беззнаковые длинные целые при использовании строк формата, так как новая функция Xcode возвращает предупреждение, если вы пытаетесь выйти из NSInteger, как если бы у него была известная длина. Точно так же вы должны быть осторожны при отправке их переменным или аргументам, которые вводятся как ints, так как вы можете потерять некоторую точность в процессе.
в целом, если вы не ожидаете, чтобы иметь сотни тысяч из них в памяти сразу, проще использовать NSInteger, чем постоянно беспокоиться о разнице между ними.
в настоящее время (сентябрь 2014) я бы рекомендовал использовать NSInteger/CGFloat
при взаимодействии с iOS API и т. д., Если вы также создаете свое приложение для arm64.
Это потому, что вы, вероятно, получите неожиданные результаты при использовании float
, long
и int
типы.
пример: FLOAT / DOUBLE vs CGFLOAT
в качестве примера возьмем метод делегата UITableView tableView:heightForRowAtIndexPath:
.
в 32-битном приложении он будет работать нормально, если это написано так:
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
float
- 32-разрядное значение, а 44, которые вы возвращаете, - 32-разрядное значение.
Однако, если мы скомпилируем / запустим этот же фрагмент кода в 64-битной архитектуре arm64, 44 будет 64-битным значением. Возврат 64-разрядного значения, когда ожидается 32-разрядное значение, даст неожиданную высоту строки.
вы можете решить эту проблему с помощью CGFloat
тип
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
этот тип представляет собой 32-разрядную float
в 32-разрядной среде и 64-бит double
в 64-разрядной среде. Поэтому при использовании этого типа метод всегда будет получать ожидаемый тип независимо от среды компиляции / выполнения.
то же самое верно для методов, которые ожидают целых чисел.
Такие методы будут ожидать 32-бит int
значение в 32-разрядной среде, и 64-разрядную long
в 64-разрядной среде. Вы можете решить этот случай, используя тип NSInteger
служит int
или long
на основе компиляции/выполнения устоячивое.
на iOS в настоящее время не имеет значения, используете ли вы int
или NSInteger
. Это будет иметь большее значение, если / когда iOS перейдет на 64-бит.
проще говоря, NSInteger
С int
s в 32-битном коде (и, следовательно, 32-битный длинный) и long
s на 64-разрядный код (long
в 64-битный код в 64-разрядный, а 32-разрядного в 32-разрядный код). Наиболее вероятная причина использования NSInteger
вместо long
не нарушать существующий 32-битный код (который использует int
s).
CGFloat
имеет ту же проблему: on 32-бит (по крайней мере, на OS X), это float
; на 64-битном, это double
.
обновление: С введением iPhone 5s, iPad Air, iPad Mini с Retina и iOS 7 Теперь вы можете создавать 64-битный код на iOS.
обновление 2: также, используя NSInteger
s помогает в совместимости Swift-кода.
int = 4 байта (фиксированный независимо от размера архитектора) NSInteger = зависит от размера архитектора (например, для 4 byte architect = 4 byte nsinteger size)