Objective-C Language
Eigenschaften
Suche…
Syntax
- @property (optional_attributes, ...) Typbezeichner;
- @synthesize Identifier = optional_backing_ivar;
- @ dynamischer Bezeichner ;
Parameter
Attribut | Beschreibung |
---|---|
atomic | Implizit. Aktiviert die Synchronisation in synthetisierten Zugriffsmethoden. |
nonatomic | Deaktiviert die Synchronisierung in den synthetisierten Zugriffsmethoden. |
readwrite | Implizit. Synthetisiert Getter, Setter und Backing-Ivar. |
readonly | Synthetisiert nur die Getter-Methode und das Hintergrund-Ivar, die direkt zugewiesen werden können. |
getter= Name | Gibt den Namen der Getter-Methode an, implizit ist propertyName . |
setter= Name | Gibt den Namen der Setter-Methode an. setPropertyName: lautet setPropertyName: Doppelpunkt : muss ein Teil des Namens sein. |
strong | Implizit für Objekte unter ARC . Das Hintergrund-Ivar wird mit __strong synthetisiert, wodurch die Freigabe von referenzierten Objekten verhindert wird. |
retain | Synonym für strong . |
copy | Wie strong , aber der synthetisierte Setter ruft -copy auf den neuen Wert auf. |
unsafe_unretained | Implizit, außer für Objekte unter ARC. Das Hintergrund-Ivar wird mithilfe von __unsafe_unretained synthetisiert, was (für Objekte) zu einem baumelnden Zeiger führt, sobald das referenzierte Objekt freigegeben wird. |
assign | Synonym für unsafe_unretained . Geeignet für Nicht-Objekttypen. |
weak | Backing-Ivar wird mit __weak synthetisiert. Der Wert wird daher aufgehoben, sobald das referenzierte Objekt freigegeben wird. |
class | Eigenschaftszugriffspunkte werden als Klassenmethoden anstelle von Instanzmethoden synthetisiert. Es wird kein Sicherungsspeicher synthetisiert. |
nullable | Die Eigenschaft akzeptiert nil Werte. Wird hauptsächlich für die schnelle Überbrückung verwendet. |
nonnull | Die Eigenschaft akzeptiert keine nil . Wird hauptsächlich für die schnelle Überbrückung verwendet. |
null_resettable | Die Eigenschaft akzeptiert nil Werte in Setter, gibt aber nie nil Wert von Getter. Ihre benutzerdefinierte Implementierung von Getter oder Setter muss dieses Verhalten sicherstellen. Wird hauptsächlich für die schnelle Überbrückung verwendet. |
null_unspecified | Implizit. Die Eigenschaft gibt keine Behandlung von nil . Wird hauptsächlich für die schnelle Überbrückung verwendet. |
Was sind Eigenschaften?
Hier ist eine Beispielklasse, die mehrere Instanzvariablen enthält, ohne Eigenschaften zu verwenden:
@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
Dies ist eine Menge Boilerplate-Code, um eine einfache Instanzvariable zu erstellen. Sie müssen die Instanzvariable erstellen und Zugriffsmethoden erstellen, die nichts anderes tun, als die Instanzvariable festzulegen oder zurückzugeben. Mit Objective-C 2.0 hat Apple also Eigenschaften eingeführt, mit denen der Boilerplate-Code ganz oder teilweise automatisch generiert wird.
Hier ist die obige Klasse mit Eigenschaften umgeschrieben:
@interface TestClass
@property NSString *someString;
@property int someInt;
@end
@implementation testClass
@end
Eine Eigenschaft ist eine Instanzvariable, die mit automatisch generierten Gettern und Setters gepaart wird. Für eine Eigenschaft mit dem Namen someString
heißen Getter und Setter someString
bzw. setSomeString:
Der Name der Instanzvariablen ist standardmäßig der Name der Eigenschaft, der ein Unterstrich vorangestellt ist (daher heißt die Instanzvariable für someString
_someString
. Dies kann jedoch mit einer @synthesize
Direktive im Abschnitt @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
Auf Eigenschaften kann durch Aufruf der Getter und Setter zugegriffen werden:
[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);
Sie können auch mit Punktnotation aufgerufen werden:
testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);
Kundenspezifische Getter und Setter
Die Standardeigenschafts-Getter und -Setzer können überschrieben werden:
@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
Dies kann nützlich sein, um beispielsweise eine verzögerte Initialisierung bereitzustellen (indem der Getter überschrieben wird, um den Anfangswert festzulegen, falls er noch nicht festgelegt wurde)
- (NSString *)someString {
if (_someString == nil) {
_someString = [self getInitialValueForSomeString];
}
return _someString;
}
Sie können auch eine Eigenschaft erstellen, die ihren Wert im Getter berechnet:
@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
Eigenschaften, die zu Aktualisierungen führen
Dieses Objekt, Shape
verfügt über ein Eigenschaftsbild image
das von numberOfSides
und sideWidth
. Wenn einer von ihnen eingestellt ist, muss das image
neu berechnet werden. Die Neuberechnung ist jedoch vermutlich lang und muss nur einmal durchgeführt werden, wenn beide Eigenschaften festgelegt sind. Shape
bietet die Shape
die Möglichkeit, beide Eigenschaften festzulegen und nur einmal neu zu berechnen. Dies erfolgt durch direktes Setzen der Eigenschafts-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
Wenn Eigenschaften zugewiesen werden (mithilfe von object.property = value
), wird die Setter-Methode setProperty:
aufgerufen. Dieser Setter kann, auch wenn er von @synthesize
bereitgestellt wird, überschrieben werden, wie in diesem Fall für numberOfSides
und sideWidth
. Wenn Sie jedoch die Ivar-Eigenschaft einer Eigenschaft direkt festlegen (über property
wenn das Objekt self oder object->property
), wird der Getter oder Setter nicht aufgerufen, sodass Sie beispielsweise mehrere Eigenschaftssätze ausführen können, die nur eine Aktualisierung oder aufrufen Bypass-Nebeneffekte, die vom Setter verursacht werden.