Espacio de tecnologia, software libre y sus derivados. Una horda de monos entrenados escriben de vez en cuando por aqui algunas noticias, opiniones e incluso alguna que otra cosa fuera del tema. Maqueros, favor de abstenerse que no somos lo suficientemente guapos.

Piano daemon

Archive for Programacion

Uso de las Listas de Propiedades las famosas “.plist” en Objetive C

screen-shot-2012-01-14-at-40246-pm.png

Basicamente este sera el contenido del fichero que hemos generado en raiz /

screen-shot-2012-01-14-at-40605-pm.png

Aunque agregando las siguientes lineas a nuestra aplicacion de ejemplo… podemos realizar el flujo en sentido contrarios….
Si asi es … convertir el plist en datos instanciados en nuestra app e imprimirlos.

screen-shot-2012-01-14-at-40911-pm.png

screen-shot-2012-01-14-at-41111-pm.png

Uso de Bloques en Objetive C

screen-shot-2012-01-14-at-33843-pm.png

Al correr el anterior ejemplo tendremos como resultado 12 y 30…

Los bloques tienen un tipo de retorno y ademas aceptan parametros como una funcion (en caso de no pasarle parametros se pondra utilizara la palabra reservada void).

Ademas de esto el bloque de codigo utiliza a la variables que estan fuera del bloque (pero dentro de la funcion)…. como si se tratacen de variables globales…

Ahora un bloque que recibe parametros…

screen-shot-2012-01-14-at-34755-pm.png

El uso de NSNumber en Objetive C

El Siguiente codigo fallara…

screen-shot-2012-01-13-at-71829-pm.png

Observemos lo que sucede al ejecutarlo

screen-shot-2012-01-13-at-72008-pm.png

Para que lo anterior no nos truene tendremos que envolver al integer en una clase NSNumber.. Ya que NSMutableArray esta diseñado prar objetos… y no para tipos de datos primitivos

screen-shot-2012-01-13-at-72302-pm.png

Observemos que ahora la cosa funciona

screen-shot-2012-01-13-at-72450-pm.png

NSMutableString … La manera de concatenar cadenas y modificarlas en objetive C

screen-shot-2012-01-13-at-65953-pm.png

Ahora ejecutemos el anterior codigo… notese que agregue un NSLog mas… abajo de “super green”

screen-shot-2012-01-13-at-70155-pm.png

Aqui podemos notar tambien como se eliminan un conjunto de caracteres de la cadena y como se insertan otros en cierta posicion..

screen-shot-2012-01-13-at-70522-pm.png

screen-shot-2012-01-13-at-70710-pm.png

Los Arreglos NSMutableArray en objetive C

screen-shot-2012-01-13-at-64803-pm.png

A diferencia de los NSArray… a estos se les pueden agregar y objetos al gusto…

NSDictionary en Objetive C

Los diccionarios en Objetive C son como los hashes en perl …
o como los Diccionarios en Python,
O como los arreglos asociativos en Php
o como los Hashmap en Java
o como los hashes en ruby.

El siguiente ejemplo al invocar el indice @Dog … esto nos retornara “House pet”

Nota.. al igual que los NSArray … se debe finalizar la inicializacion de un NSDictionary con un nil (el equivalente a NULL en otros lenguajes).

screen-shot-2012-01-13-at-63009-pm.png

Tambien podemos recorrerlo al viejo estilo de los perleros el foreach

screen-shot-2012-01-13-at-63917-pm.png

NSArray en objetive C

Los NSArray son arreglos en objetive c que no se pueden ALTERAR una vez definidos…. y tienen que terminal en null..

He aqui la forma en que se iteran…

screen-shot-2012-01-13-at-62024-pm.png

Tambien podemos recorrelo al estilo foreach

screen-shot-2012-01-13-at-63636-pm.png

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)

learnobjectivec-referencecounting.png

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….

screen-shot-2012-01-12-at-33827-pm.png

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.

screen-shot-2012-01-12-at-11230-pm.png

Cuando tienes algún error de este tipo el programa terminará y el xcode te mandará un mensaje que dice algo como:

screen-shot-2012-01-12-at-114935-am.png

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.

screen-shot-2012-01-12-at-115710-am.png

¿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

screen-shot-2012-01-12-at-124243-pm.png

screen-shot-2012-01-12-at-124425-pm.png

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):

screen-shot-2012-01-12-at-125300-pm.png

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”
screen-shot-2012-01-12-at-125523-pm.png

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.

screen-shot-2012-01-12-at-113123-am.png

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.

« Entradas anteriores · Entradas mas recientes »