ios objective-c types nsinteger

ios - Cuándo usar NSInteger vs. int



objective-c types (8)

A partir de este momento (septiembre de 2014) recomendaría el uso de NSInteger/CGFloat al interactuar con API de iOS, etc., si también está creando su aplicación para arm64. Esto se debe a que probablemente obtendrá resultados inesperados cuando utilice los tipos float , long e int .

EJEMPLO: FLOTADOR / DOBLE vs CGFLOAT

Como ejemplo tomamos el método delegado tableView:heightForRowAtIndexPath:

En una aplicación de solo 32 bits, funcionará bien si se escribe así:

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

float es un valor de 32 bits y el 44 que está devolviendo es un valor de 32 bits. Sin embargo, si compilamos / ejecutamos este mismo fragmento de código en una arquitectura arm64 de 64 bits, el 44 será un valor de 64 bits. Devolver un valor de 64 bits cuando se espera un valor de 32 bits dará un alto de fila inesperado.

Puedes resolver este problema usando el tipo CGFloat

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

Este tipo representa una float 32 bits en un entorno de 32 bits y un double 64 bits en un entorno de 64 bits. Por lo tanto, al usar este tipo, el método siempre recibirá el tipo esperado independientemente del entorno de compilación / tiempo de ejecución.

Lo mismo es cierto para los métodos que esperan números enteros. Tales métodos esperarán un valor int 32 bits en un entorno de 32 bits y un long 64 bits en un entorno de 64 bits. Puede resolver este caso utilizando el tipo NSInteger que sirve como int o long según el entorno de compilación / tiempo de ejecución.

¿Cuándo debo usar NSInteger vs. int cuando desarrollo para iOS? Veo en el código de ejemplo de Apple que usan NSInteger (o NSUInteger ) cuando pasan un valor como argumento a una función o devuelven un valor desde una función.

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

Pero dentro de una función solo están usando int para rastrear un valor

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

He leído (me han dicho) que NSInteger es una forma segura de hacer referencia a un entero en un entorno de 64 bits o de 32 bits. ¿Por qué usar int en absoluto?


Debe usar NSIntegers si necesita compararlos con valores constantes como NSNotFound o NSIntegerMax, ya que estos valores diferirán en sistemas de 32 y 64 bits, así que los valores de índice, conteos y similares: use NSInteger o NSUInteger.

No duele usar NSInteger en la mayoría de las circunstancias, excepto que ocupa el doble de memoria. El impacto de la memoria es muy pequeño, pero si tiene una gran cantidad de números flotando en un momento dado, puede hacer una diferencia al usar caracteres.

Si SÍ usa NSInteger o NSUInteger, deseará convertirlos en enteros largos o enteros largos sin signo cuando use cadenas de formato, ya que la nueva función Xcode devuelve una advertencia si intenta cerrar sesión en NSInteger como si tuviera una longitud conocida. Igualmente, debe tener cuidado al enviarlos a variables o argumentos que se escriben como ints, ya que puede perder cierta precisión en el proceso.

En general, si no espera tener cientos de miles de ellos en la memoria a la vez, es más fácil usar NSInteger que preocuparse constantemente por la diferencia entre los dos.


En iOS, actualmente no importa si usa int o NSInteger . Importa más si / cuando iOS se mueve a 64 bits.

En pocas palabras, NSInteger s son int s en código de 32 bits (y por lo tanto de 32 bits de longitud) y s long en código de 64 bits (s long en código de 64 bits son de 64 bits de ancho, pero 32 bits en 32- código de bits). La razón más probable para usar NSInteger lugar de por long es no romper el código de 32 bits existente (que usa int s).

CGFloat tiene el mismo problema: en 32 bits (al menos en OS X), es float ; En 64 bits, es double .

Actualización: con la introducción del iPhone 5s, iPad Air, iPad Mini con Retina y iOS 7, ahora puede crear un código de 64 bits en iOS.

Actualización 2: Además, el uso de NSInteger ayuda con la interoperabilidad del código Swift.


OS X es "LP64". Esto significa que:

int es siempre de 32 bits.

long long es siempre de 64 bits.

NSInteger y long siempre son de tamaño puntero. Eso significa que son 32 bits en sistemas de 32 bits y 64 bits en sistemas de 64 bits.

La razón por la que NSInteger existe es porque muchas API heredadas utilizaron incorrectamente int lugar de long para contener variables de tamaño de puntero, lo que significaba que las API debían cambiar de int a long en sus versiones de 64 bits. En otras palabras, una API tendría firmas de función diferentes dependiendo de si está compilando para arquitecturas de 32 bits o de 64 bits. NSInteger pretende enmascarar este problema con estas API heredadas.

En su nuevo código, use int si necesita una variable de 32 bits, long long si necesita un entero de 64 bits y long o NSInteger si necesita una variable de tamaño de puntero.


Por lo general, desea usar NSInteger cuando no sabe en qué tipo de arquitectura de procesador podría ejecutarse su código, por lo que, por alguna razón, puede desear el tipo de int más grande posible, que en sistemas de 32 bits es solo un int , mientras que en un 64 sistema de bits es un long

Me quedaría con el uso de NSInteger lugar de int / long menos que usted lo requiera específicamente.

NSInteger / NSUInteger se definen como * typedef * s dinámico para uno de estos tipos, y se definen así:

#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

Con respecto al especificador de formato correcto que debe utilizar para cada uno de estos tipos, consulte la sección Guía de programación de cadenas en Dependencias de plataforma


Si profundizas en la implementación de NSInteger:

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

Simplemente, el typedef NSInteger hace un paso por usted: si la arquitectura es de 32 bits, usa int , si es de 64 bits, usa long . Al usar NSInteger, no necesita preocuparse por la arquitectura en la que se está ejecutando el programa.


int = 4 byte (tamaño fijo independientemente del arquitecto) NSInteger = depende del tamaño del arquitecto (por ejemplo, para 4 byte architect = 4 byte NSInteger tamaño)


¿Por qué usar int en absoluto?

Apple usa int porque para una variable de control de bucle (que solo se usa para controlar las iteraciones del bucle) el tipo de datos int está bien, tanto en el tamaño del tipo de datos como en los valores que puede contener para su bucle. No es necesario el tipo de datos dependiente de la plataforma aquí. Para una variable de control de bucle, incluso un int 16 bits funcionará la mayor parte del tiempo.

Apple usa NSInteger para un valor de retorno de función o para un argumento de función porque en este caso el tipo de datos [tamaño] es importante , porque lo que está haciendo con una función es comunicar / pasar datos con otros programas o con otras piezas de código; ver la respuesta a ¿ Cuándo debo usar NSInteger vs int? en tu propia pregunta ...

ellos [Apple] usan NSInteger (o NSUInteger) cuando pasan un valor como argumento a una función o devuelven un valor desde una función.