El Ciclo de vida del Objeto en Objetive C
Asi como los pajaritos y las abejas de nuestro mundo real, objectos dentro de la aplicacion tiene un ciclo de vida. Ellos nacen (via un alloc o un new), viven ( reciben mensajes y crean cosas utiles ), hacen amigos (via composicion y por ser pasados como argumentos a metodos), y eventualmente moriran cuando su periodo de vida este sobrepasado. Cuando todo esto sucede, el polvo que de ellos queda (memoria) es reciclado y reaprovechado para la nueva generacion.
1. — Conteo por Referencia (Reference Counting)
Cocoa usa una tecnica conocida como conteo por referencia, algunas veces tambien llamada “retain counting“. Donde cada objeto tiene un integer asociado con el, este entero asociado es conocido como su referencia de conteo o retain count. Cuando una parte de codigo esta interesada en un objeto, esta parte de codigo incrementara la referencia de conteo de dicho objeto (diciendo “Yo estoy estoy interesado en este objeto cabron!”). Pero cuando esta parte de codigo haya satisfecho su mas bajos instintos con el objeto y ya no lo necesite mas…, entonces el conteo de referencia de dicho objeto pasara a Cero. Entonces como a nadie mas le interesa este objeto, entonces pasara a ser destruido y su memoria reciclada.
Cuando un objeto es creado via alloc o new, o via a copy, el conteo de referencia del objeto es aumentado a 1. Para incrementar el conteo de referencia de un objeto se invoca el metodo retain. Para decrementar el conteo de referencia de un objeto se invoca el metodo release.
Cuando un objeto esta siendo destruido es por que su conteo de referencia a alcanzado su valor 0, Objective-C mandara automaticamente la ejecucion del metodo dealloc del objeto.
Veamos un ejemplo… aqui defino mi clase y la implementacion de la misma
@interface RetainTracker : NSObject
@end // RetainTracker
@implementation RetainTracker
- (id) init {
if (self = [super init]) {
NSLog (@"init: Retain count of %d.",
[self retainCount]);
}
return (self);
} // init
- (void) dealloc
{
NSLog (@"dealloc called. Bye Bye.");
[super dealloc];
} // dealloc
@end // RetainTracker
Y aqui hago uso de ella para demostrar el uso de retain y release
int main (int argc, const char *argv[])
{
RetainTracker *tracker = [RetainTracker new];
// count: 1
[tracker retain]; // count: 2
NSLog (@"%d", [tracker retainCount]);
[tracker retain]; // count: 3
NSLog (@"%d", [tracker retainCount]);
[tracker release]; // count: 2
NSLog (@"%d", [tracker retainCount]);
[tracker release]; // count: 1
NSLog (@"%d", [tracker retainCount]);
[tracker retain]; // count 2
NSLog (@"%d", [tracker retainCount]);
[tracker release]; // count 1
NSLog (@"%d", [tracker retainCount]);
[tracker release]; // count: 0, dealloc it
return (0);
} // main
Y aqui nuestra salida a pantalla….
El conteo de referencia nos ayuda a evitar una gran cantidad de problemas surguidos al compartir memoria entre diferentes clases y objetos, pero plantea problemas a la hora de decidir donde y quien debe ejecutar los releases.
2. — Propietario del Objeto (Object Ownership)
Si un metodo tiene que devolver un objeto nuevo y no guarda ningun puntero al mismo ¿Como libera la memoria de este nuevo objeto … ? como no guarda el puntero no puede hacer el release más tarde, tampoco lo puede ejecutar inmediatamente porque si lo hace se liberará la memoria en este mismo momento y producirá el fallo al intentar usarla. Y tampoco es buena idea devolverlo sin el release, por que en este caso se producira un leak si la otra clase no la libera. Aqui entra en juego la convencion Ownership
Según esta convención, todo objeto es responsable de liberar la memoria que crea o retiene, pero aporta un par de reglas extras para solucionar el problema anterior:
Regla A)
Cuando un objeto va a utilizar memoria creada por otro método debe hacer un retain para evitar su liberación prematura.
Regla B)
Todo objeto debe liberar la memoria creada (mediante métodos alloc, copy o new) y retenida (mediante método retain), invocando el método release en algún momento en su ciclo de vida. Por cada alloc/retain ejecutado debe hacerse un release.
Regla C)
Si un método devuelve un objeto que no va a liberar, el método deberá llamarse allocXXX, copyXXX o newXXX (donde XXX se sustituye por el nombre que elijas). De esta forma, el que invoca el método puede conocer esta característica y, aplicando la regla B podra librerarla. Esta misma regla podría aplicarse N veces si cada método devuelve a su vez el objeto nuevo a su padre.
Ejemplo convención Ownership:
- (Clase *) newObjectWithData:(NSData *)data{
//Creamos el objeto
Clase *object = [[Clase alloc] init];
//Ejecutamos lo que sea
[object setData:data];
//Devolvemos el objeto
return object;
}
En este ejemplo podemos hacer la devolución gracias a haber nombrado al método newXXX, que indicará al que lo invoque que el objeto de tipo Clase * devuelto está sin liberar.
3.– Autorelease
Por último, tenemos un último recurso que nos ayudará a gestionar la memoria. Lo he dejado al final porque no pienso tratarlo aqui, ya que desaconsejo su uso, y es mejor no mostrarlo para evitar una mala praxis.
Zombies las estrategia contra EXC_BAD_ACCESS en X-Code
Es traumante encontrarse con este error y no saber por qué sucede, bueno, sucede generalmente porque liberaste (release) algo que no deberías o antes de que deberías, o no lo liberaste, o sea algún retain de más o de menos.
Cuando tienes algún error de este tipo el programa terminará y el xcode te mandará un mensaje que dice algo como:
Para saber dónde está el error, suele ser un problema en proporcion al tamaño de tu codigo, a razon de esto existe algo llamado NSZombie. Y como funciona esto.. ? Los Zombies permiten que los objetos que ya han sido liberados (su retain count ha llegado a 0) mantegan una copia vacia (a esta copia es el famoso zombie). Asi entonces cuando en nuestro código llamemos al zombie, este te advertirá que estas llamando a una instancia que ya fue liberada.
¿Cómo habilito los objetos NSZombie?
Abre el proyecto en el que quieres habilitar los zombies, y ubicate sobre el ejecutable del proyecto, abre el menú contextual y selecciona Get Info, luego Ve a la pestaña de Arguments, agrega en el fondo la variable NSZombieEnabled y pon el valor en YES
Ahora corremos de nuevo el programa, solo que ahora, cuando el programa se interrumpa, no terminará, sino que se pausa, y podemos ver que manda un mensaje como el siguiente (lo que esta en amarillito):
Ahora si tratamos de continuar la ejecucion de la aplicacion podemos notar que el zombie nos dice….
Hey en esta direccion de memoria hay un Objeto vacio que fue usado como “En este caso la clase Exercise”

Manejo de Memoria en Ipad
El manejo de memoria es muy importante, sobre todo en dispositivos portatiles como el iPhone y el iPod, a razon de que no cuentan con los recursos tan grandes que tienen las computadoras de escritorio actualmente.
Retain y Release
El contador de retain (retain count) se utiliza para llevar un registro de las referencias activas hacia un mismo objeto. Todos los objetos tienen internamete este contador, de tal manera que si el contador de retain es mayor a cero, significa que aún esta siendo utilizado en alguna parte del codigo, pero una vez que llega a cero, se debe liberar la memoria que estaba usando.
Cuando se quiere agregar una referencia al objeto se llama al método retain: [objeto retain]; esto aumenta el contador de retain en 1 y cuando deseamos remover una referencia llamaremos al método release: [objeto release]; esto disminuye el contador de retain en 1. Una vez que el contador llega a 0 (cero), se libera la memoria automáticamente con una llamada a [self dealloc]. Los métodos retain y release estan definidos en NSObject.
Algunas reglas generales son
* Debes liberar con release todo lo que tu creaste, todo lo que es creado con alloc, o new, o los metodos que contienen la palabra copy (newObject, copyWithZone, mutableCopy,…), tambien debes darle release, si manualmente diste un retain.
* En otras palabras debe haber un (ni mas ni menos) release por cada retain, alloc, new o copy.
* Para liberar la memoria puedes usar tanto release, como autorelease, la diferencia es que release, disminuye el contador de retain inmediatamente, mientras que autorelease lo hará en un momento en el futuro.
* Un objeto que es recibido como retorno de algún método no debe ser liberado en el método receptor, por lo general esta garantizado que sea válido mientras dure el método que lo recibe e incluso puede ser devuelto al método que lo llamó. Aunque existen algunas excepciones como algunas aplicaciones multihilo, donde una combinación de retain y release o autorelease asegurarán que el objeto se mantenga válido mientras sea necesario.
* Si deseas conservar un objeto en una variable de instancia debes darle retain o copy, generalmente se hace a través de accesadores.
Ciclo de vida de una App Iphone
Conocer el ciclo de vida es importante para saber como se inicializa la app y asi poder configurarlo, de la misma manera, nos servira para saber el funcionamiento general de la gestion de memoria y los eventos.
El framework UIKit es el responsable de mantener en funcionamiento la aplicacion. Durante la ejecucion de la aplicacion esta recibe eventos, y estos se tienen que responder. Estos eventos son recibidos por el objeto UIApplication, integrado en el framework UIKit, y son respondidos segun nuestro codigo.
Justo despues de pulsar el icono, la aplicacion procede a ejecutarse llamando a su funcion main. Una vez ejecutada, el UIKit se encargara de inicializar la aplicacion, primero cargando la interfaz de usuario, y seguidamente dejando paso al event loop, el bucle principal de la aplicacion. Es en este bucle donde el UIKit se encarga de coordinar todos los eventos recibidos con las respuestas que nuestro programa quiere dar.
Cuando se pulsa el boton Home para salir de la aplicacion, el UIKit llama a metodos de nuestro codigo para avisar que se cierra la aplicacion, de esta manera, podemos guardar el estado de la aplicacion si queremos. Una vez ejecutado nuestro codigo, la aplicacion se cierra y se libera de la memoria del iPhone.
El codigo de main
El codigo del main siempre es el mismo para todas las aplicaciones de iPhone.
La instancia de UIApplicationMain
Esta es la clase principal de toda aplicacion de iPhone. Una vez ejecutado el main, se crea la aplicacioon propia de iPhone, es decir, con el UIApplicationMain, nosotros especificamos quien va ser el delegado principal, la clase principal, y tambien que vista se cargara en primera instancia.
¿Por que se especifica el delegado?
Nuestra aplicacion responde a mensajes, y es por eso que creamos los delegados para que se encarguen de responderlos. De esta manera evitamos hacer subclases de UIApplication, ya que al formar parte de UIKit, estas tienen una complejidad bastante alta, y es muchisimo mas comodo delegar que sobrescribir metodos.
Event Loop
El event loop o bucle principal es una de las caracteristicas mas importantes de iPhone, y una de las caracteristicas mas diferenciadoras de otros estilos de programacion como es Java o C++. Y es que de manera totalmente transparente al programador, al ejecutar una aplicacion en iPhone esta queda atrapada en este bucle de manera automatica, capturando todos los eventos del usuario, sean tactiles, de acelerometros, de internet, etc.
Con el event loop no nos tenemos que preocupar de crear nosotros el bucle tal y como hari?amos en Java o C, UIApplicationMain se encarga de gestionarlo automaticamente.
El Patron Delegate del Ipad
Basicamente este patron, permite personalizar el comportamiento de un “objeto A” evitandonos la necesidad de tener que hacerle una subclase (evitandonos asi ..el clasico estilo de programacion como la hecha en java… ), mediante el uso de otro “objeto B” (un delegado) que realizara el trabajo por el “objeto A”.
Protocolos y Delegados
Un protocolo declara métodos que pueden ser implementados por cualquier clase. Los protocolos no son clases por si mismos. Simplementen definen una interfaz que otros objetos son responsables de implementar. Cuando implementa los métodos de un protocolo en una de sus clases, se dice que su clase se ajusta al protocolo.
Los protocolos son utilizados para especificar la interfaz para objetos delegados. Un objeto delegado es un objeto que actua en nombre de, o coordinandose con, otro objeto. La mjor manera de entender la relación entre protocolos, delegados, y otros objetos es simplemente verlo con un ejemplo.
La clase UIApplication implementa el comportamiento requerido por una aplicación. En lugar de forzarte a hacer una subclase de UIApplication para recibir simples notificaciones sobre el estado actual de la aplicación, la clase UIApplication entrega estas notificaciones llamando a métodos específicos asignados a un objeto delegado. Un objeto que implementa los métodos del protocolo UIApplicationDelegate pueden recibir estas notificaciones y proporcionar una respuesta apropiada.
En Sintesis un protocolo en objetive C sera la forma que tendra una clase de decir “Si alguien quiere trabajar conmigo, debera saber hacer esta serie de tareas”, algunas de caracter obligatorio y otras de caracter opcional.
Con esto, estamos diciendo que cualquier clase que quiera trabajar con el objeto que define este protocolo debe ser capaz de responder al metodo metodoDeInstanciaQueDebeImplementarse
Por parte de la clase que define el protocolo, lo normal es referenciar al objeto que va a cumplirlo como delegado. Es decir, un delegado es un objeto que cumple el protocolo y al que vamos a mandar los mensajes correspondientes.
Con esta nomenclatura le hemos dicho que la variable delegate sera una objeto de cualquier tipo que cumpla con el protocolo MiProtocolo. Es decir, que implemente el metodo medotoDeInstanciaQueDebeImplementarse
Responsabilidades de los Controlandores de Vistas en el IPAD (Los ViewControllers)
Un Controlador de vista es a menudo el objeto (target) que responde a los controles sobre la pantalla. El patron de diseño Target-Action es quien hace posible que el controller sea conciente de cualquier cambio en la vista.
Los Controladores de vista tienen otras responsabilidades vitales en IPAD tambien…
Administran un conjunto de vistas — Inclullendo la creacion de estas o liberacion de las mismas en situaciones de baja memoria.
Responder al cambio en la orientacion del dispositivo
Creacion de una vista modal –(una ventana hijo de dialogo… al estilo los dialogos en javascript)
Vistas en MVC de Ipad
En el universo iPad ( como seran los planetas de ese universo ?… … que mamon), los objetos vista son responsables de la vista en la arquitectura Model-View-Controller architecture.
Una vista es una area rectangular en la pantalla. El contenido de la vista es esa porcion de datos y controles que aparece entre la barra superior y las barra inferiores.
En el framework UIKit, en realidad las ventanas son un especial tipo de vista.
Pero cuales son las responsabilidades de una Vista ?
Las vistas son la principal manera para que nuestras aplicaciones interactuen con los usuarios. Esta interaccion puede sucitarce de 2 maneras:
* Vistas que desplieguen contenido. Por Ejemplo, dibujar animaciones en pantalla. En esencia, el objeto vista desplegara datos del objeto modelo.
* Vistas recogen todo el toqueteo que el usuario hace en la pantalla (los touch events). Los touch events responderan cuando el usuario toque por ejemplo un boton.
La Herarquia de las Vistas
Las vistas y las subvistas crear una gerarquia de vistas. Existen dos maneras de mirar esto “visualmentte (como el usuario percibe esto) y herarquicamente (Como nosotros estructuremos esto).
Premisas de la Gerarquia de vistas en IPAD
* El contenido de la vista es agregado a la ventana como una subvista.
* Vistas agregadas a la subvista … seran sub sub vistas .. y tendran como supervista a la subvista
* Una vista puede tener una (y solo una) supervista y zero o mas supervistas.
* Una vista tiene la capacidad de administrar sus subvistas.
Crear o Modificar una herarquia de vistas puede realizarce mediante el Interface Builder o Programaticamente mediante el UIKit framework, este automaticamente se encargara de todas las relaciones asociadas con las vistas.
Los tipos de Vistas a usar
La clase UIView define las propiedades basicas de una vista. Aunque en la practica se utilizan clases que heredan de esta.
* Container views -- UIScrollView -- UITableView -- UIToolbar * Controls -- UIView -- UIControl * Display views -- UIImageView -- UILabel -- UIProgressView -- UIActivityIndicatorView * Text and Web views -- UIWebView -- UITextView * Alert views and action sheets -- UIAlertView -- UIActionSheet * Navigation views -- UITabBar -- UINavigationBar * The window

















