Ricerca…


Sintassi

  • @property ( optional_attributes, ... ) identificativo del tipo ;
  • @synthesize identifier = optional_backing_ivar ;
  • @ identificatore dinamico;

Parametri

Attributo Descrizione
atomic Implicito. Abilita la sincronizzazione nei metodi di accesso sintetizzati.
nonatomic Disabilita la sincronizzazione nei metodi di accesso sintetizzati.
readwrite Implicito. Sintetizza getter, setter e backing ivar.
readonly Sintetizza solo il metodo getter e il supporto ivar, che possono essere assegnati direttamente.
getter= nome Specifica il nome del metodo getter, implicito è propertyName .
setter= nome Specifica il nome del metodo setter, l' setPropertyName: è setPropertyName: Colon : deve essere una parte del nome.
strong Implicito per oggetti sotto ARC . Il backing ivar viene sintetizzato usando __strong , che impedisce la deallocazione dell'oggetto referenziato.
retain Sinonimo per strong .
copy Uguale a strong , ma anche il setter sintetizzato chiama -copy sul nuovo valore.
unsafe_unretained Implicito, tranne per oggetti sotto ARC. Il backing ivar viene sintetizzato usando __unsafe_unretained , che (per obejcts) risulta in un puntatore pendente una volta che l'oggetto referenziato rilascia.
assign Sinonimo di unsafe_unretained . Adatto per tipi diversi da oggetti.
weak Il backing ivar viene sintetizzato usando __weak , quindi il valore verrà annullato una volta che l'oggetto referenziato è stato deallocato.
class Gli accessor di proprietà sono sintetizzati come metodi di classe, invece che come metodi di istanza. Nessuna memoria di supporto è sintetizzata.
nullable La proprietà accetta valori nil . Utilizzato principalmente per il bridging rapido.
nonnull La proprietà non accetta valori nil . Utilizzato principalmente per il bridging rapido.
null_resettable La struttura accetta nil valori in setter, ma mai ritorna nil valori da getter. La tua implementazione personalizzata di getter o setter deve garantire questo comportamento. Utilizzato principalmente per il bridging rapido.
null_unspecified Implicito. La proprietà non specifica la gestione dei valori nil . Utilizzato principalmente per il bridging rapido.

Quali sono le proprietà?

Ecco una classe di esempio che ha un paio di variabili di istanza, senza usare le proprietà:

@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

Questo è un bel po 'di codice boilerplate per creare una semplice variabile di istanza. Devi creare la variabile di istanza e creare metodi di accesso che non fanno altro che impostare o restituire la variabile di istanza. Quindi con Objective-C 2.0, Apple ha introdotto le proprietà, che generano automaticamente alcuni o tutti i codici standard.

Ecco la classe precedente riscritta con le proprietà:

@interface TestClass

@property NSString *someString;
@property int someInt;

@end


@implementation testClass

@end

Una proprietà è una variabile di istanza abbinata a getter e setter generati automaticamente. Per una proprietà chiamata someString , getter e setter sono chiamati someString e setSomeString: rispettivamente. Il nome della variabile di istanza è, per impostazione predefinita, il nome della proprietà preceduto da un trattino basso (quindi la variabile di istanza per someString viene chiamata _someString , ma può essere sostituita con una direttiva @synthesize nella sezione @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

È possibile accedere alle proprietà chiamando getter e setter:

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

Possono anche essere accessibili usando la notazione dot:

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

Getter e setter personalizzati

I getter e i setter di proprietà predefiniti possono essere sovrascritti:

@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

Ciò può essere utile per fornire, ad esempio, l'inizializzazione pigra (ignorando il getter per impostare il valore iniziale se non è stato ancora impostato):

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

Puoi anche creare una proprietà che calcoli il suo valore nel 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

Proprietà che causano aggiornamenti

Questo oggetto, Shape ha image proprietà che dipende da numberOfSides e sideWidth . Se uno di questi è impostato, l' image deve essere ricalcolata. Ma il ricalcolo è presumibilmente lungo e deve essere fatto una volta sola se entrambe le proprietà sono impostate, quindi la Shape fornisce un modo per impostare entrambe le proprietà e ricalcolare solo una volta. Questo viene fatto impostando direttamente la proprietà ivars.

In 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

In 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

Quando le proprietà vengono assegnate a (usando object.property = value ), viene chiamato il metodo setter setProperty: . Questo setter, anche se fornito da @synthesize , può essere sovrascritto, come in questo caso per numberOfSides e sideWidth . Tuttavia, se si imposta direttamente la proprietà di ivar (tramite la property se l'oggetto è self o object->property ), non chiama getter o setter, consentendo di fare cose come set di proprietà multiple che chiamano solo un aggiornamento o bypass effetti collaterali causati dal setter.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow