Когда использовать 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 331

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 тип данных в порядке, как в размере типа данных, так и в значениях, которые он может содержать для вашего цикла. здесь нет необходимости в зависимых от платформы типах данных. для переменной управления циклом даже 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 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-битный длинный) и 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 помогает с быстрой совместимости кода.

int = 4 байта (фиксированный независимо от размера архитектора) NSInteger = зависит от размера архитектора (например, для 4-байтового архитектора = 4-байтовый размер NSInteger)