Subscribe Twitter Twitter

jueves, 22 de julio de 2010

Diferencias entre NSInteger , int y NSNumber

Estos tres tipos de datos se usan en objective C pero aunque parezcan iguales entre algunos de ellos existen tanto diferencias como similitudes.

Vamos a empezar por los tipos de datos NSInteger e int. ambos representan un dato de tipo entero y son tipos primitivos por lo que no es necesario reservar memoria dinámicamente e inicializarlos mediante el método init antes de empezar a usarlos. simplemente se declaran y si se quiere se les asigna un valor.

En concreto el tipo int es para arquitectura de 32 bits y se ha heredado del lenguaje C, por el contrario NSInteger es de objective-C y puede tener un tamaño u otro siendo esa su principal diferencia por lo que en nuestro caso para el desarrollo de apps para Iphone/Ipod/Ipad nos resulta ajeno y podemos usar cualquiera de los dos.

En cambio el tipo de dato NSNumber es un objeto que almacena un dato numérico ya sea entero/real/double... y por ello es necesario usar punteros ya que pertenece a objective-c sí hay que reservar memoria dinámicamente y a continuación inicializarlos, ya hemos visto en otros post que lo podemos inicializar a un valor concreto y sino la inicialización por defecto se realiza llamando al método init (con este método el objeto apunta a c)

int myEntero = 4;
NSInteger miEntero_2 = 5
;
NSNumber *miObjetoNumerico = [[NSNumber alloc] initWithInt:40]; // En este caso lo inicializamos con un valor de tipo entero en concreto el 40

sino la inicialización por defecto sería:

NSNumber *miObjetoNumerico = [[NSNumber alloc] init];

Sobre las dudas de "por ello es necesario usar punteros ya que pertenece a objective-c" fue un despiste, ya que es habitual el uso de punteros en objetive C.
¡Gracias a los que nos avisaron del error!

23 comentarios:

uptheapp dijo...

Hola Noemí, parece que falta un ; detrás del 5. Puede dar lugar al despiste.

int myEntero = 4; NSInteger *miEntero_2 = 5 NSNumber *miObjetoNumerico = [[NSNumber alloc] initWithInt:40]

Muchas gracias por tus explicaciones!!

Por cierto, para cambiarle el texto a un boton, no vale con la propiedad .text? como al label? es que quise hacerlo siguiendo tu videotutorial y no me deja hacerlo.

Albert dijo...

Si lo inicializamos por defecto (NSNumber *miObjetoNumerico = [[NSNumber alloc] init]), ¿que valor tiene *miObjetoNumerico? porque no se le asigna ningún valor.

¿Porque se tiene que reservar memoria para NSNumber y no para NSInteger?

Gracias

Unknown dijo...

Enhorabuena por el empujón que le estáis dando al blog llenándolo de contenido de calidad.

Una pregunta. ¿Vais a tratar sólo tutoriales de C/Objective C o tenéis pensado hacer algo de Appcelerator Titanium? Yo lo utilizo porque me parece un engorro tener que aprender otro lenguaje más.

Un saludo y enhorabuena.

Soulless dijo...

Albert, NSNumber es un objeto mientras que NSInteger es un dato primitivo como el int, float… En objetive-C los objetos no se manejan directamente, sino que se hace a través de punteros. Por ello has de reservar memoria para dicho objeto NSNumber, para luego colocar al puntero *miObjetoNumerico apuntando a él. Por el contario, los datos primitivos se declaran y se utilizan directamente. Aunque al principio puede no parecer lógico esta manera de proceder, a medidas que cojas experiencia en Objective-C verás como es increiblemente efectivo el utilizar punteros a objetos.

Por otro lado, (NSNumber *miObjetoNumerico = [[NSNumber alloc] init]), reserva memoria pero no lo inicializa con ningún valor, con lo que se dice que *miObjetoNumerico esta a NIL. NIL es la forma de indicar vacío, sin valor… OJO decir que un objeto esta a nil no es igual que decir que un objeto tiene valor cero.

uptheapp, sobre tu pregunta ¿quieres cambiarle el texto en tiempo de ejecución, que cambie de forma dinámica, o establecer un texto fijo durante toda la ejecución del programa?

Unknown dijo...

En el ultimo parrafo se dice la frase "y por ello es necesario usar punteros ya que pertenece a objective-c..." a que nos referimos cuando se habla de punteros?

GRACIAS

Unknown dijo...

Están muy padres tus explicaciones, antes que nada felicidades ya que no es fácil encontrar información en nuestro lenguaje.

Quisiera saber si falta mucho para poder ver ejemplos con bases de datos.

Saludos.

Jose dijo...

Muchísimas gracias por explicarlo tan bien, sois the best.

Saludos.

Noemí dijo...

Vamos a seguir poniendo ejemplos y videotutoriales y claro que vamos a hacer en breve de bases de datos, como he comentado en un comentario nos hemos quedado sin ordenadores y hasta mañana no nos los devuelven por ello no ha habido más tutos.

Noemí dijo...

Hola Eden los punteros en realidad son una referencia a un tipo de dato concreto, haré un post sobre ello para que quede mejor explicado.

Noemí dijo...

Hola uptheapp para modificar dinámicamente el texto de un botón debes hacerlo si mal no recuerdo (no tengo el mac) [miBoton setTitle:@"Nuevo texto" forState:UIControlStateNormal];

UIControlStateNormal nos indica el estado en el que se encuentra el botón por defecto, ni seleccionado ni nada, es el estado normal, también se puede poner el número 0.

Recuerda que deberás declarar el botón como IBOutlet y poner el @property y el synthesize correspondiente.

Noemí dijo...

Hola Toneti con respecto a tus preguntas:
- Si es cierto que puedes usar int o NSInteger indistintamente :).
- Si, al ser tipos de datos primitivos no hay que reservar memoria, no hay que hacerlo es automático ya que por el tipo que es se sabe lo que ocupa. Siempre que hagas reserva de memoria para usar por ejemplo NSNumber hay que liberarla con el método release.
- NSNumber no es para 64bits, para 64bits es NSInteger pero lo que quiero decir es que aqui(iphone/ipod/ipad) se pueden usar ambos int (para 32) y NSInteger para 64 .

Resumen:
int y NSInteger: Datos primitivos de tipo entero (32 y 64 bits) respectivamente. Nunca se reserva memoria.

NSNumber: Apunta a un objeto numérico que puede ser entero, real... en este caso SIEMPRE se reserva memoria y después cuando se deje de usar se LIBERA.

Unknown dijo...

Muy buen comentario el del botón con título dinámico, ha hacer pruebas se ha dicho.

Saludos y gracias.

Eduardo dijo...

Me parece excelente tu idea de crear un espacio para enseñar programacion para iOS en español, deseo felicitarte y desearte mucha suerte en este y en todos tus siguientes proyectos

Julián dijo...

Hola, creo que estás equivocada, NSInteger no hace falta declararlo como puntero, NSInteger es un entero del tamaño de palabra del procesador, en 64 bits es de 64 bits y en 32 bits es de 32 bits, de hecho tu en ese código no estas declarando ningún entero, estas declarando un puntero a un entero, si tu sacas por pantalla tu puntero, verás el numero ese, pero en realidad es una dirección, si quieres saber lo que contiene esa dirección, tienes que hacer así: NSLog(%"i",*miEntero_2); y verás que te da error, porque tu estas accediendo a una dirección que no sabes que contiene y muy probablemente este fuera del trozo de memoria de tu programa, si escribieras en esa dirección, en windows es fácil que escoñaras algo, porque alomejor estas escribiendo encima de una dirección del SO, pero aquí en UNIX, te salta un error, porque tu no puedes escribir fuera de tu programa.
Bueno el resumen de todo este rollo, es que estás cometiendo un fallo garrafal, que no hay que tratar NSInteger como puntero, sino como un tipo primitivo normal, de hecho es un tipo primitivo normal:
#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

// CÓDIGO SACADO DE

y si dices que hay que hacer uso de punteros porque es de Objective-C, te digo que no tienes ni idea de que estás haciendo ni de que estás programando, y te aconsejo repasar conceptos de la memoria, memoria dinámica, la pila, como funciona a grandes rasgos el SO, el lenguaje C, los punteros... y todos esos conceptos que si quieres ser una buena programadora deberías dominar.
Un saludo.

Julián dijo...

Donde pone // CÓDIGO SACADO DE
falta poner de Foundation/NSObjcRuntime.h

Curro dijo...

Hola Julián, esto se discutió ya en otra entrada hace un ratito.

http://helloworldiphone.blogspot.com/2010/04/objective-c-variables.html#comments

Julián dijo...

Vale ya lo he visto, pues parece que Noemí no se ha dado por enterada, de todas formas felicidades por el blog, está muy bien salvo esas cosillas...
Un saludo.

Pablo dijo...

Hola Julian, varias cosas me gustaría comentarte sobre tus aportaciones:
1-. La gente que hacemos este blog no revisamos este blog las 24h del día fines de semanas incluidos, nos llegan multitud de notificaciones sobre comentarios por varios medios y si por cada notificación tuviéramos que entrar a contestarla al momento etc tendríamos que dedicar la totalidad del día al blog.

2-. No me parece tu tono el apropiado en ninguno de los sentidos, es una mezcla de prepotencia al hablar y de exigencia el cual no es bien recibido en este blog.

3-. Ya centrado en el motivo del comentario: Que era de tipo primitivo se comentó desde el principio. Que al ser objetive c hay que usar punteros es un error, ya sabemos que no es vinculante, aunque si que suele ser habitual el uso de punteros en objetive c y fue un despiste al escribir el post y al escribir el ejemplo por lo que se modificará tal y como veo que ya avisó algún usuario más.

4-. El motivo de este blog es intentar enseñar a todo el mundo con unos conocimientos básicos como poder crear sus propias aplicaciones, las aplicaciones que podrán crear a través de lo aprendido en este blog usaran elementos habituales vistos en las aplicaciones de la appstore (TabBars,TableViews,Vistas,MapKit,uso del acelerómetro,BD etc..) pero no requieren altos conocimientos sobre la pila, gestión de memoria,punteros etc.. en caso de estar interesados en ese tipo de conceptos les recomendamos estudiar ingeniería informática,ya que esos temas según nuestra propia experiencia se estudian en primero o segundo de carrera en función del plan de estudios o no sé si tal vez tienes un blog hablando sobre ello, porque de ser así podías compartir la dirección para que pueda ser util a la gente que desee profundizar en esos temas, sino es así te ánimo a que lo hagas.

Un saludo

Julián dijo...

Vale tienes razón solo quería notificar que eso estaba mal, y vale os pido perdón por no usar el tono adecuado.
Y bueno también quería decir que no tengo blog ni intención de hacerlo, y que estudio bachillerato.
Un saludo, y de nuevo lo siento.

Morlet dijo...

Hola, es la primera vez que entro a este blog, y te voy a felicitar, porque esta muy entendible y es un herramienta util, muchas gracias por el esfuerzo que haces para ayudarnos a comprender el desarrollo en xcode

Aram dijo...

Hola,

No entro en si las formas de decir las cosas está bien.
Pero el tío tiene razón.
NSInteger es un tipo de dato (como el int) entero. Nada mas. Todo lo que es aplicable al int es aplicable a NSInteger. Sólo que NSInteger tendrá la ventaja de tener un tamaño u otro dependiendo de la plataforma. Por lo que si queréis ser previsores y tener un código "independiente" de la plataforma es recomendable usar NSInteger en vez del int. No hay más.

También sugeriría cambiar esta frase:
"... y por ello es necesario usar punteros ya que pertenece a objective-c"
por esta
Si estáis usando objetos objective-c tenéis que usar punteros.
Queda más corto y creo más claro aunque no sea del todo preciso.
Un saludo y seguid así.

PynSoft dijo...

Gracias Aram!, ya está cambiado tal y como varios habíais comentado en los comentarios.

Un saludo!

Noemí dijo...

Hola Raúl yo creo que te pueden resultar útiles estos post: http://helloworldiphone.blogspot.com/2010/04/objective-c-metodos-especiales-alloc-e.html

http://helloworldiphone.blogspot.com/2010/07/la-gestion-memoria-i.html

Un saludo y gracias por tu comentario(de lo del printf haremos un post :)

Publicar un comentario