Objective-C Language
Proprietà
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.