Objective-C Language
Egenskaper
Sök…
Syntax
- @property (optional_attributes, ...) Typ identifierare;
- @synthesize identifier = option_backing_ivar ;
- @dynamisk identifierare ;
parametrar
Attribut | Beskrivning |
---|---|
atomic | Implicit. Aktiverar synkronisering i syntetiserade accessormetoder. |
nonatomic | Inaktiverar synkronisering i de syntetiserade accessormetoderna. |
readwrite | Implicit. Syntetiserar getter, setter och backning ivar. |
readonly | Syntetiserar endast getter-metoden och ivar som backas, som kan tilldelas direkt. |
getter= namn | Anger namnet på getter-metoden, implicit är propertyName . |
setter= namn | Anger namnet på setter-metoden, implicit är setPropertyName: Kolon : måste vara en del av namnet. |
strong | Implicit för objekt under ARC . Den __strong syntetiseras med hjälp av __strong , vilket förhindrar omlokalisering av refererat objekt. |
retain | Synonym för strong . |
copy | Samma som strong , men den syntetiserade setteren kallar också -copy på det nya värdet. |
unsafe_unretained | Implicit, med undantag för objekt under ARC. Den stödjande ivaren syntetiseras med hjälp av __unsafe_unretained , vilket (för objekter) resulterar i dinglande pekare när det refererade objektet har omlokaliserats. |
assign | Synonym för unsafe_unretained . Lämplig för andra typer än objekt. |
weak | Säkerhetskopiering av ivar syntetiseras med __weak , så värdet kommer att upphöra när det refererade objektet har omlokaliserats. |
class | Fastighetstillträdare syntetiseras som klassmetoder istället för instansmetoder. Ingen stödlagring är syntetiserad. |
nullable | Egenskapen accepterar nil . Används främst för snabb överbryggning. |
nonnull | Egenskapen accepterar inte nil . Används främst för snabb överbryggning. |
null_resettable | Egenskapen accepterar nil i setter, men returnerar aldrig nil från getter. Din anpassade implementering av getter eller setter måste säkerställa detta beteende. Används främst för snabb överbryggning. |
null_unspecified | Implicit. Egenskapen anger inte hantering av nil . Används främst för snabb överbryggning. |
Vad är egenskaper?
Här är en exempelklass som har ett par instansvariabler utan att använda egenskaper:
@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
Det här är en hel del pannplåtkod för att skapa en enkel instansvariabel. Du måste skapa instansvariabeln och skapa åtkomstmetoder som inte gör något annat än att ställa in eller returnera instansvariabeln. Så med Objekt-C 2.0 introducerade Apple egenskaper som automatiskt genererar en del av eller hela källan för pannan.
Här är ovanstående klass omskrivna med egenskaper:
@interface TestClass
@property NSString *someString;
@property int someInt;
@end
@implementation testClass
@end
En egenskap är en instansvariabel parad med auto-genererade getters och setters. För en egenskap som heter someString
kallas getter och setter someString
respektive setSomeString:
Namnet på instansvariabeln är som standard namnet på egenskapen förinställd med en understreck (så instansvariabeln för someString
kallas _someString
, men det kan åsidosättas med ett @synthesize
direktiv i avsnittet @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
Egenskaper kan nås genom att ringa Getters och Seters:
[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);
De kan också nås med punktnotation:
testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);
Anpassade bokstäver och uppsättare
Standardegenskaperna och -inställningarna kan åsidosättas:
@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
Detta kan vara användbart för att till exempel ge lat initiering (genom att åsidosätta gettern för att ställa in initialvärdet om det ännu inte har ställts in):
- (NSString *)someString {
if (_someString == nil) {
_someString = [self getInitialValueForSomeString];
}
return _someString;
}
Du kan också skapa en egenskap som beräknar dess värde i 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
Egenskaper som orsakar uppdateringar
Detta objekt, Shape
har en egenskap image
som beror på numberOfSides
och sideWidth
. Om någon av dem är inställd måste image
beräknas om. Men omberäkningen är förmodligen lång och behöver bara göras en gång om båda egenskaperna är inställda, så Shape
ger ett sätt att ställa in båda egenskaperna och bara beräkna en gång. Detta görs genom att ställa in fastigheten ivars direkt.
I 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
I 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
När egenskaper tilldelas (med hjälp av object.property = value
) setProperty:
Denna inställare, även om den tillhandahålls av @synthesize
, kan åsidosättas, som den är i detta fall för numberOfSides
och sideWidth
. Men om du ställer in en ivars ivar direkt (genom property
om objektet är själv, eller object->property
), ringer det inte getter eller setter, vilket gör att du kan göra saker som flera egendomsuppsättningar som bara kallar en uppdatering eller bypass biverkningar orsakade av setteren.