Recherche…


Syntaxe

  • @property ( optional_attributes, ... ) identifiant de type ;
  • identificateur de @synthesize = optional_backing_ivar;
  • identifiant dynamique

Paramètres

Attribut La description
atomic Implicite. Permet la synchronisation dans les méthodes d'accès synthétisées.
nonatomic Désactive la synchronisation dans les méthodes d'accesseur synthétisées.
readwrite Implicite. Synthétise getter, setter et back ivar.
readonly Synthétise uniquement la méthode getter et le support ivar, qui peuvent être assignés directement.
getter= nom Spécifie le nom de la méthode getter, implicite est propertyName .
setter= nom Spécifie le nom de la méthode setter, l'implicite est setPropertyName: Colon : doit faire partie du nom.
strong Implicite pour les objets sous ARC . La sauvegarde ivar est synthétisée en utilisant __strong , ce qui empêche la désallocation de l'objet référencé.
retain Synonyme de strong .
copy Même chose que strong , mais le composeur synthétisé appelle également -copy sur la nouvelle valeur.
unsafe_unretained Implicite, sauf pour les objets sous ARC. La sauvegarde ivar est synthétisée à l'aide de __unsafe_unretained , qui (pour obejcts) se traduit par un pointeur en suspens une fois que l'objet référencé est désalloué.
assign Synonyme de unsafe_unretained . Convient aux types sans objet.
weak Le backar ivar est synthétisé en utilisant __weak , donc la valeur sera annulée une fois que l'objet référencé sera désalloué.
class Les accesseurs de propriétés sont synthétisés en tant que méthodes de classe, au lieu de méthodes d'instance. Aucun stockage de sauvegarde n'est synthétisé.
nullable La propriété accepte les valeurs nil . Principalement utilisé pour les ponts rapides.
nonnull La propriété n'accepte pas les valeurs nil . Principalement utilisé pour les ponts rapides.
null_resettable La propriété accepte les valeurs nil dans setter, mais ne renvoie jamais de valeurs nil partir de getter. Votre implémentation personnalisée de getter ou setter doit garantir ce comportement. Principalement utilisé pour les ponts rapides.
null_unspecified Implicite. La propriété ne spécifie pas le traitement des valeurs nil . Principalement utilisé pour les ponts rapides.

Quelles sont les propriétés?

Voici un exemple de classe qui comporte deux variables d’instance, sans utiliser les propriétés:

@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

C'est un code assez standard pour créer une variable d'instance simple. Vous devez créer la variable d'instance et créer des méthodes d'accès qui ne font rien sauf définir ou renvoyer la variable d'instance. Ainsi, avec Objective-C 2.0, Apple a introduit des propriétés qui génèrent automatiquement tout ou partie du code standard.

Voici la classe ci-dessus réécrite avec les propriétés:

@interface TestClass

@property NSString *someString;
@property int someInt;

@end


@implementation testClass

@end

Une propriété est une variable d'instance associée à des getters et des setters générés automatiquement. Pour une propriété appelée someString , le getter et le setter sont appelés someString et setSomeString: respectivement. Le nom de la variable d'instance est, par défaut, le nom de la propriété préfixée par un trait de soulignement (la variable d'instance pour someString est appelée _someString , mais elle peut être remplacée par une directive @synthesize dans la section @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

On peut accéder aux propriétés en appelant les getters et les setters:

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

On peut également y accéder en utilisant la notation par points:

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

Getters et régleurs personnalisés

Les getters et setters de propriétés par défaut peuvent être remplacés:

@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

Cela peut être utile pour fournir, par exemple, une initialisation différée (en remplaçant le getter pour définir la valeur initiale s'il n'a pas encore été défini):

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

Vous pouvez également créer une propriété qui calcule sa valeur dans le getter:

@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

Propriétés provoquant des mises à jour

Cet objet, Shape possède une image propriété qui dépend de numberOfSides et de sideWidth . Si l'un d'eux est défini, l' image doit être recalculée. Mais le recalcul est probablement long et ne doit être effectué qu'une seule fois si les deux propriétés sont définies. Ainsi, la Shape permet de définir les deux propriétés et de ne recalculer qu'une seule fois. Cela se fait en définissant directement la propriété ivars.

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

Lorsque des propriétés sont affectées à (à l'aide de object.property = value ), la méthode setter setProperty: est appelée. Ce setter, même s'il est fourni par @synthesize , peut être remplacé, comme c'est le cas pour numberOfSides et sideWidth . Toutefois, si vous définissez directement le paramètre ivar d'une propriété (via la property si l'objet est self ou object->property ), il n'appelle pas getter ou setter, ce qui vous permet de faire des choses comme plusieurs jeux de propriétés contourner les effets secondaires causés par le passeur.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow