jun 19

En este artículo vamos explicar los métodos de inicialización de objetos en Objective-C. Veremos cómo sobrecargarlos correctamente y como crear nuestros propios de la forma más correcta.

Antes que nada vamos a ver cómo solemos sobrecargar el método init en nuestras clases que heredan del NSObject y entender el porque lo hacemos así.

-(id)init{
 
    if (self = [super init]){
 
      // Aquí incializamos nuestros variables
 
    }
    return self;
}

Con el [super init] inicializamos las variables de la clase padre. Esta inicialización está en un if para no inicializar nuestro código y devolver un objeto corrupto con variables a medio inicializar ya que si el [super init] devuelve un nil ya no entraremos dentro del if. De esta forma o retornamos un objeto completo o nil. Dentro del if al inicializar nuestras variables si se produce algún error tenemos que retornar nil.

Regla: antes de incializar nuestras variables SIEMPRE tenemos que incializar la clase padre. Siempre vamos de arriba hacía abajo en la jerarquía.

Vamos a suponer que tenemos una clase Alumno definido de la siguiente manera:

@interface Alumno : NSObject {
	NSString *nombre;
	NSString *apellido;
}
 
@property (nonatomic, retain)NSString *nombre;
@property (nonatomic, retain)NSString *apellido;
 
@end

Y su implementación es la siguiente:

@implementation Alumno
@synthesize nombre, apellido;
 
@end

Entonces, usaríamos esta clase de la siguiente manera:

Alumno *a = [[Alumno alloc] init];
a.nombre = @"Pepe";
a.apellido = @"Garcia";
NSLog(@"Nombre de alumno: %@ y  apellido: %@", a.nombre, a.apellido);

Fijaros que para inicializar llamamos el init que no está definido en nuestra clase pero viene heredada de la clase padre (NSObject) por lo que al hacer esta llamada las variables nombre y apellido no se inicializan pero si se inicializan las variables de la clase padre.
Es natural querer que nuestra clase Alumno tenga un inicializador tipo “initConNombre:(NSString *)n yApellido:(NSString *)a” que nos permita poner directamente el nombre y el apellido del alumno.

También puede que queramos un inicializador que sólo acepte el nombre del alumno tipo “initConNombre:(NSString *)n”.

Entonces, para organizar bien nuestros inicializadores, no duplicar código y asegurarnos que todas las variables se inicializan correctamente independientemente del incializador usado se usan los inicializadores designados (designed initializators).

Inicializadores designados

Cada clase ha de tener un inicializador designado y será este el único inicializador que llamara a [super init] y se encargará de inicializar todas las variables usados por nuestra clase. El resto de los inicializadores tendrán que llamar a este inicializador.

Volviendo a nuestra clase alumno. ¿Cuál es su inicializador designado?
Lo tenemos que decidir nosotros. Casi siempre es el inicializador con más parámetros. En nuestro caso el inicializador por defecto sera este: -(id)initConNombre:(NSString *)n yApellido:(NSString *)a
A continuación vamos a ver como implementaríamos los inicializadores de nuestra clase.

#import "Alumno.h"
 
#define NOMRE_POR_DEFECTO @""
#define APELLIDO_POR_DEFECTO @""
 
@implementation Alumno
@synthesize nombre, apellido;
 
-(id)initConNombre:(NSString *)n yApellido:(NSString *)a
{
    if (self = [super init])
    {
 
    }
    return self;
}
 
-(id)initConNombre:(NSString *)n{
	return [self initConNombre:n yApellido:APELLIDO_POR_DEFECTO];
}
 
-(id)init{
	return [self initConNombre:NOMRE_POR_DEFECTO];
}
 
@end

Fijaros como desde el init llamamos al siguiente inicializador pasándole el valor por defecto, a su vez el siguiente inicializador llama al inicializador por defecto quien es el único en hacer el [super init] e incializar las variables del Alumno. Esto en la jerga de Objective-C se llama “initialization chain”. Usar cadenas de inicialización reduce la probabilidad de que cometamos errores y facilita el mantenimiento del código.

También es muy importante darse cuenta del porque definimos nuestro propio init sobreescribiendo el init (que es el init designado) del NSObject. Si no lo hubieramos hecho al hacer [[Alumno alloc] init] inicializaríamos las variables del NSObject pero no las de Alumno. Al sobreescribirlo conseguimos inicializar tanto nuestras variables como las de la clase padre. Siempre, al heredar de una clase tenemos que sobreescribir el inicializador designado de esa clase.

Resumen de las tres reglas (recomendaciones)

Regla 1: antes de incializar nuestras variables SIEMPRE tenemos que incializar la clase padre. Siempre vamos de arriba hacía abajo en la jerarquía.

Regla 2: los inicializadores de nuestras clases siempre tienen que acabar llamando al inicializador designado de nuestra clase.

Regla 3: siempre tenemos que sobreescribir el inicializador designado de la clase de la que heredamos.

Podéis descargar el código con el ejemplo que hemos visto en este artículo.
Inicializadores

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)

3 Responses to “Los inicializadores en Objective-C”

  1. toni toni dice:

    Muchas gracias por el ejemplo,

    muy claro y conciso ;)

    Saludos

    VA:F [1.9.8_1114]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.8_1114]
    Rating: 0 (from 0 votes)
  2. Aram Aram dice:

    De nada !
    Me alegro que te haya sido útil.

    Un saludo

    VN:F [1.9.8_1114]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.8_1114]
    Rating: 0 (from 0 votes)
  3. Marcela Marcela dice:

    queria consultar lo siguiente:
    como puedo agregar funcionalidades de html5 al xcode? incluyendo las imagenes??

    O dejar una carpeta con html en el ipad}???.. uhhhh.. no se me ocurre… por favor ayuda!!

    VA:F [1.9.8_1114]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.8_1114]
    Rating: 0 (from 0 votes)

Leave a Reply

*
preload preload preload