Objective-C Language
Eigendommen
Zoeken…
Syntaxis
- Type- ID @property ( optioneel_attributen, ... );
- @synthesize identifier = optioneel_backing_ivar ;
- @ dynamische identificatie ;
parameters
Attribuut | Beschrijving |
---|---|
atomic | Impliciete. Maakt synchronisatie mogelijk in gesynthetiseerde accessormethoden. |
nonatomic | Schakelt synchronisatie uit in de gesynthetiseerde accessormethoden. |
readwrite | Impliciete. Synthetiseert getter, setter en backing ivar. |
readonly | Synthetiseert alleen de getter-methode en achtergrond-ivar, die direct kunnen worden toegewezen. |
getter= naam | Specificeert de naam van de getter-methode, impliciet is propertyName . |
setter= naam | Specificeert de naam van de setter-methode, impliciteit is setPropertyName: Dubbelpunt : moet een deel van de naam zijn. |
strong | Impliciet voor objecten onder ARC . De backing ivar wordt gesynthetiseerd met __strong , waardoor deallocatie van het gerefereerde object wordt voorkomen. |
retain | Synoniem voor strong . |
copy | Hetzelfde als strong , maar de gesynthetiseerde setter roept ook -copy op de nieuwe waarde op. |
unsafe_unretained | Impliciet, behalve voor objecten onder ARC. De backing ivar wordt gesynthetiseerd met behulp van __unsafe_unretained , wat (voor obejcts) resulteert in een bengelende wijzer zodra het gerefereerde object dealloceert. |
assign | Synoniem voor unsafe_unretained . Geschikt voor niet-objecttypen. |
weak | Backing ivar wordt gesynthetiseerd met behulp van __weak , dus de waarde wordt tenietgedaan zodra het object waarnaar wordt verwezen, is toegewezen. |
class | Eigendomstoegangen worden gesynthetiseerd als klassemethoden in plaats van instantiemethoden. Er wordt geen achtergrondopslag gesynthetiseerd. |
nullable | De eigenschap accepteert nil . Hoofdzakelijk gebruikt voor snelle bruggen. |
nonnull | De eigenschap accepteert geen nil . Hoofdzakelijk gebruikt voor snelle bruggen. |
null_resettable | De eigenschap accepteert nil in setter, maar retourneert nooit nil van getter. Uw aangepaste implementatie van getter of setter moet dit gedrag waarborgen. Hoofdzakelijk gebruikt voor snelle bruggen. |
null_unspecified | Impliciete. De eigenschap geeft geen verwerking van nil . Hoofdzakelijk gebruikt voor snelle bruggen. |
Wat zijn eigenschappen?
Hier is een voorbeeldklasse die een aantal instantievariabelen heeft, zonder eigenschappen te gebruiken:
@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
Dit is nogal wat boilerplate-code om een eenvoudige instantievariabele te maken. U moet de instantievariabele maken en toegangsmethoden maken die niets anders doen dan de instantievariabele instellen of retourneren. Dus met Objective-C 2.0 introduceerde Apple eigenschappen die automatisch een deel van of alle boilerplate-code genereren.
Hier is de bovenstaande klasse herschreven met eigenschappen:
@interface TestClass
@property NSString *someString;
@property int someInt;
@end
@implementation testClass
@end
Een eigenschap is een instantievariabele gekoppeld met automatisch gegenereerde getters en setters. Voor een eigenschap met de naam someString
, worden de getter en de setter respectievelijk someString
en setSomeString:
De naam van de instantievariabele is standaard de naam van de eigenschap voorafgegaan door een onderstrepingsteken (dus de instantievariabele voor someString
wordt _someString
, maar dit kan worden genegeerd met een @synthesize
instructie in de sectie @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
Eigenschappen kunnen worden geopend door de getters en setters te bellen:
[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);
Ze kunnen ook worden geopend met behulp van puntnotatie:
testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);
Aangepaste getters en setters
De standaard eigenschap getters en setters kunnen worden opgeheven:
@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
Dit kan handig zijn om bijvoorbeeld luie initialisatie te bieden (door de getter te negeren om de beginwaarde in te stellen als deze nog niet is ingesteld):
- (NSString *)someString {
if (_someString == nil) {
_someString = [self getInitialValueForSomeString];
}
return _someString;
}
U kunt ook een eigenschap maken die de waarde ervan in de getter berekent:
@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
Eigenschappen die updates veroorzaken
Dit object, Shape
heeft een eigenschap image
die afhankelijk is van numberOfSides
en sideWidth
. Als een van beide is ingesteld, moet de image
opnieuw worden berekend. Maar herberekening is vermoedelijk lang en hoeft slechts eenmaal te worden uitgevoerd als beide eigenschappen zijn ingesteld, dus de Shape
biedt een manier om beide eigenschappen in te stellen en slechts eenmaal opnieuw te berekenen. Dit wordt gedaan door de eigenschap ivars rechtstreeks in te stellen.
In vorm. 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
Wanneer eigenschappen worden toegewezen aan (met object.property = value
), wordt de setter-methode setProperty:
aangeroepen. Deze setter, zelfs indien geleverd door @synthesize
, kan worden opgeheven, zoals in dit geval voor numberOfSides
en sideWidth
. Als u echter de eigenschap ivar van een eigenschap rechtstreeks instelt (via property
als het object self is, of object->property
), wordt de getter of setter niet aangeroepen, zodat u dingen kunt doen zoals meerdere eigenschappensets die slechts één update oproepen of bypass-bijwerkingen veroorzaakt door de setter.