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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow