Когда использовать 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
определяются как * dynamictypedef
* 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
тип данных в порядке, как в размере типа данных, так и в значениях, которые он может содержать для вашего цикла. здесь нет необходимости в зависимых от платформы типах данных. для переменной управления циклом даже 16-битint
будет делать большую часть времени.Apple использует
NSInteger
для возвращаемого значения функции или для функции аргумент потому что в этом случае тип данных [размер] имеет значение, потому что то, что вы делаете с функцией, передает/передает данные с другими программами или с другими частями кода; см. ответ на когда я должен использовать NSInteger vs 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
tolong
в их 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 помогает с быстрой совместимости кода.