Buscar..


Sintaxis

  • @property ( optional_attributes, ... ) identificador de tipo ;
  • @synthesize identifier = optional_backing_ivar ;
  • identificador @dynamic;

Parámetros

Atributo Descripción
atomic Implícito. Habilita la sincronización en métodos de acceso sintetizados.
nonatomic Desactiva la sincronización en los métodos de acceso sintetizados.
readwrite Implícito. Sintetiza getter, setter y respaldo ivar.
readonly Sintetiza solo el método getter y el respaldo de ivar, que se pueden asignar directamente.
getter= nombre Especifica el nombre del método getter, implícito es propertyName .
setter= nombre Especifica el nombre del método de establecimiento, implícito es setPropertyName: Colon : debe ser parte del nombre.
strong Implícito para objetos bajo ARC . El respaldo ivar se sintetiza utilizando __strong , lo que evita la desasignación del objeto referenciado.
retain Sinónimo de strong .
copy Igual que strong , pero el definidor sintetizado también llama a la -copy en el nuevo valor.
unsafe_unretained Implícito, excepto para los objetos bajo ARC. El soporte ivar se sintetiza utilizando __unsafe_unretained , que (para objetos) da como resultado un puntero colgante una vez que el objeto referenciado se desasigna.
assign Sinónimo para unsafe_unretained . Adecuado para tipos sin objeto.
weak El respaldo de ivar se sintetiza utilizando __weak , por lo que el valor se __weak una vez que se desasigne el objeto al que se hace referencia.
class Los accesores de propiedades se sintetizan como métodos de clase, en lugar de métodos de instancia. No se sintetiza ningún almacenamiento de respaldo.
nullable La propiedad acepta valores nil . Utilizado principalmente para puentes rápidos.
nonnull La propiedad no acepta valores nil . Utilizado principalmente para puentes rápidos.
null_resettable La propiedad acepta valores nil en el establecedor, pero nunca devuelve valores nil de getter. Su implementación personalizada de getter o setter debe garantizar este comportamiento. Utilizado principalmente para puentes rápidos.
null_unspecified Implícito. La propiedad no especifica el manejo de valores nil . Utilizado principalmente para puentes rápidos.

¿Qué son las propiedades?

Aquí hay una clase de ejemplo que tiene un par de variables de instancia, sin usar propiedades:

@interface TestClass : NSObject {
    NSString *_someString;
    int _someInt;
}

-(NSString *)someString;
-(void)setSomeString:(NSString *)newString;

-(int)someInt;
-(void)setSomeInt:(NSString *)newInt;

@end


@implementation TestClass

-(NSString *)someString {
    return _someString;
}

-(void)setSomeString:(NSString *)newString {
    _someString = newString;
}

-(int)someInt {
    return _someInt;
}

-(void)setSomeInt:(int)newInt {
    _someInt = newInt;
}

@end

Esto es bastante código repetitivo para crear una variable de instancia simple. Debe crear la variable de instancia y crear métodos de acceso que no hagan nada, excepto establecer o devolver la variable de instancia. Así que con Objective-C 2.0, Apple introdujo propiedades, que generan automáticamente parte o la totalidad del código repetitivo.

Aquí está la clase anterior reescrita con propiedades:

@interface TestClass

@property NSString *someString;
@property int someInt;

@end


@implementation testClass

@end

Una propiedad es una variable de instancia emparejada con captadores y definidores generados automáticamente. Para una propiedad llamada someString , el getter y setter se llaman someString y setSomeString: respectivamente. El nombre de la variable de instancia es, de forma predeterminada, el nombre de la propiedad con un guión bajo (por lo que la variable de instancia para someString se llama _someString , pero esto se puede anular con una directiva @synthesize en la sección @implementation :

@synthesize someString=foo;    //names the instance variable "foo"
@synthesize someString;    //names it "someString"
@synthesize someString=_someString;        //names it "_someString"; the default if 
                                           //there is no @synthesize directive

Se puede acceder a las propiedades llamando a los captadores y configuradores:

[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);

También se puede acceder a ellos usando notación de puntos:

testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);

Capturadores personalizados y setters

Los captadores y definidores de propiedades predeterminados se pueden anular:

@interface TestClass

@property NSString *someString;

@end

@implementation TestClass

// override the setter to print a message
- (void)setSomeString:(NSString *)newString {
    NSLog(@"Setting someString to %@", newString);
    // Make sure to access the ivar (default is the property name with a _ 
    // at the beginning) because calling self.someString would call the same
    // method again leading to an infinite recursion
    _someString = newString;
}

- (void)doSomething {
    // The next line will call the setSomeString: method
    self.someString = @"Test";
}

@end

Esto puede ser útil para proporcionar, por ejemplo, una inicialización perezosa (anulando al getter para establecer el valor inicial si aún no se ha establecido):

- (NSString *)someString {
    if (_someString == nil) {
        _someString = [self getInitialValueForSomeString];
    }
    return _someString;
}

También puedes hacer una propiedad que calcula su valor en el captador:

@interface Circle : NSObject

@property CGPoint origin;
@property CGFloat radius;
@property (readonly) CGFloat area;

@end

@implementation Circle

- (CGFloat)area {
    return M_PI * pow(self.radius, 2);
}

@end

Propiedades que causan actualizaciones

Este objeto, Shape tiene una image propiedad que depende de numberOfSides y sideWidth . Si cualquiera de ellos está configurado, entonces la image debe ser recalculada. Pero el recálculo es presumiblemente largo, y solo debe hacerse una vez si ambas propiedades están establecidas, por lo que la Shape proporciona una manera de establecer ambas propiedades y solo recalcularlas una vez. Esto se hace estableciendo la propiedad ivars directamente.

En Shape.h

@interface Shape {
    NSUInteger numberOfSides;
    CGFloat sideWidth;

    UIImage * image;
}

// Initializer that takes initial values for the properties.
- (instancetype)initWithNumberOfSides:(NSUInteger)numberOfSides withWidth:(CGFloat)width;

// Method that allows to set both properties in once call.
// This is useful if setting these properties has expensive side-effects.
// Using a method to set both values at once allows you to have the side-
// effect executed only once.
- (void)setNumberOfSides:(NSUInteger)numberOfSides andWidth:(CGFloat)width;

// Properties using default attributes.
@property NSUInteger numberOfSides;
@property CGFloat sideWidth;

// Property using explicit attributes.
@property(strong, readonly) UIImage * image;

@end

En Shape.m

@implementation AnObject

// The variable name of a property that is auto-generated by the compiler
// defaults to being the property name prefixed with an underscore, for
// example "_propertyName". You can change this default variable name using
// the following statement:
// @synthesize propertyName = customVariableName;

- (id)initWithNumberOfSides:(NSUInteger)numberOfSides withWidth:(CGFloat)width {
    if ((self = [self init])) {
       [self setNumberOfSides:numberOfSides andWidth:width];
    }

    return self;
}

- (void)setNumberOfSides:(NSUInteger)numberOfSides {
    _numberOfSides = numberOfSides;

    [self updateImage];
}

- (void)setSideWidth:(CGFloat)sideWidth {
    _sideWidth = sideWidth;

    [self updateImage];
}

- (void)setNumberOfSides:(NSUInteger)numberOfSides andWidth:(CGFloat)sideWidth {
    _numberOfSides = numberOfSides;
    _sideWidth = sideWidth;

    [self updateImage];
}

// Method that does some post-processing once either of the properties has
// been updated.
- (void)updateImage {
    ...
}

@end

Cuando las propiedades se asignan a (usando object.property = value ), se llama al método setProperty: Este configurador, incluso si lo proporciona @synthesize , puede ser anulado, como lo es en este caso para numberOfSides y sideWidth . Sin embargo, si configura el ivar de una propiedad directamente (a través de la property si el objeto es self, o object->property ), no llama al captador ni al establecedor, lo que le permite hacer cosas como conjuntos de propiedades múltiples que solo llaman una actualización o Evita los efectos secundarios causados ​​por el colocador.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow