Когда использовать 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 должны были измениться сinttolongв их 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Сints в 32-битном коде (и, следовательно, 32-битный длинный) иlongs на 64-разрядный код (longв 64-битный код в 64-разрядный, а 32-разрядного в 32-разрядный код). Наиболее вероятная причина для использованияNSIntegerвместоlongэто не сломать существующий 32-битный код (который используетints).
CGFloatимеет тот же вопрос: on 32-бит (по крайней мере, на OS X), этоfloat; на 64-битном, этоdouble.обновление: С введением iPhone 5s, iPad Air, iPad Mini с Retina и iOS 7 Теперь вы можете создавать 64-разрядный код на iOS.
обновление 2: также, используя
NSIntegers помогает с быстрой совместимости кода.