lunes, 1 de agosto de 2011

¿Synthesize? Objective-C te ayuda con getters y setters

Mucho he tardado en entender de una manera clara que es @synthesize en Objective C. Y por fin sé que es, y puedo explicarlo de una manera clara. No sé si me topé con una mala ayuda, o simplemente tuve varios días malos, pero por fín lo tengo claro.

Aquí os dejo la "ayudita" de hoy.

Supongamos que tenemos una clase "Persona". La cual tendrá Nombre, Apellidos y edad como variables de clase. Tendremos pues, un header definido de la siguiente manera:

@interface Persona{
    NSString *nombre;
    NSString *apellidos;
    int edad;
}



Ahora, tendríamos que definir en nuestro modulo (el Persona.m) un getter y un setter para cada una de las variables. Es decir, deberíamos de tener algo así:

#import "Persona.h"
@implementation Persona

-(id) init
{
    if( (self=[super init])) {
        //Inicialización
    }
    return self;
}

-(NSString*) getNombre{
    return nombre;
}

-(void) setNombre:(NSString*) nuevoNombre{
    nombre = nuevoNombre;
}

//... Y así sucesivamente para las demás propiedades

@end

Lo cual, si tenemos muchas variables que deben de ser accesibles, puede ser un poco tedioso implementar cada uno de los procedimientos y funciones.

Para ellos Objective-C te ofrece las directivas @property y @synthesize. Para hacerlo funcionar tan sólo debemos añadir al header lo siguiente:

@interface Persona{
    NSString *_nombre;
    NSString *_apellidos;
    int _edad;
}

@property (nonatomic, getter=getNombre, setter=setNombre) NSString* nombre;
@property (nonatomic, getter=getApellidos, setter=setApellidos) NSString* apellidos;
@property (nonatomic, getter=getEdad, setter=setEdad) int edad;

Y en el módulo de la clase lo siguiente:

#import "Persona.h"
@implementation Persona
@synthesize nombre = _nombre;
@synthesize apellidos = _apellidos;
@synthesize edad = _edad;

-(id) init
{
    if( (self=[super init])) {
        //Inicialización
    }
    return self;
}

//... ¡Y no hay que implementar nada más!

@end

Ya tan sólo deberías de acceder a las variables de la siguiente manera:
Persona * persona = [[Persona alloc] init];
[persona setNombre: @"Daniel"];
[persona setApellidos: @"López Sánchez"];
[persona setEdad: 25];

//Y para recibir información:

int edad = [persona getEdad];

Y eso es todo por hoy.

6 comentarios:

  1. No eres el unico al que estas cosas le sonaron a chino cuando empezó con el Objective-c, pero te voy a ampliar un poco mas la informacion:

    En Primer lugar si no vas a cambiar el nombre del metodo que hace de SET y de GET no es necesario especificarlo y seria suficiente con poner:

    @property (nonatomic) NSString* nombre;

    - nonatomic vs atomic

    atomic es la forma segura de hacerlo, mediante esta propiedad hace que los metodos SET y GET sean Safe-Thread, es decir que pone un semaforo a cada metodo para que no se pueda llamar al SET desde 2 threads distintos

    Imagina por ejemplo que tu metodo SetNombre le da por hacer esto

    -(void) setNombre:(NSString*)string
    {
    if (name)
    {
    [name release];

    // en este punto, si desde algun sitio de tu aplicacion se llama
    // a este metodo daria una explosion de las buenas
    // que la propiedad sea atomic ya te evita esto

    name = nil;
    }
    }

    si tus metodos SET y GET se limitan solo a dar y a devolver la variable no es necesario ese control de Threads porque no te van a dar problemas, entonces en esos casos se usa el nonatomic


    Otro detalle importante es que una vez que tienes los metodos GET y SET definidos no es necesario llamar a estos metodos, la clase ya sabe que esas propiedades lo tienen, por tanto si asignas la variable directamente estas llamado a estos metodos (esto es muy facil de comprobar poniendo breaks)

    self.nombre = @"Pepe" ; // esto llama al SetNombre
    int miedad = self.edad; // esto llama al getEdad

    ResponderEliminar
  2. Tienes razón, gracias por las aclaraciones neofar =)

    ResponderEliminar
  3. Gracias, si no fuera por este post no lo hubiera entendido, saludos

    ResponderEliminar
  4. Espectacular, muchas gracias señores !

    ResponderEliminar