Szukaj…


Składnia

  • @property ( opcjonalny_atrybuty, ... ) identyfikator typu ;
  • @synthesize identifier = opcjonalny_powrót_powrót ;
  • @dynamiczny identyfikator ;

Parametry

Atrybut Opis
atomic Domniemany. Umożliwia synchronizację w zsyntetyzowanych metodach akcesorów.
nonatomic Wyłącza synchronizację w metodach zsyntetyzowanego akcesorium.
readwrite Domniemany. Syntezuje getter, seter i backing ivar.
readonly Syntetyzuje tylko metodę gettera i backing ivar, które można przypisać bezpośrednio.
getter= nazwa Określa nazwę metody pobierającej, domyślnie jest propertyName .
setter= nazwa Określa nazwę metody ustawiającej, implikacja to setPropertyName: Dwukropek : musi być częścią nazwy.
strong Domniemane dla obiektów objętych ARC . __strong jest syntetyzowany przy użyciu __strong , co zapobiega dealokacji obiektu, do którego __strong odwołanie.
retain Synonim strong .
copy Taki sam jak strong , ale -copy syntezator wywołuje także -copy dla nowej wartości.
unsafe_unretained Domniemane, z wyjątkiem obiektów objętych ARC. Podstawowy ivar jest syntetyzowany przy użyciu __unsafe_unretained , co (dla obejcts) powoduje zwisający wskaźnik po zwolnieniu obiektu, do którego się odwołuje.
assign Synonim dla unsafe_unretained . Odpowiedni dla typów niebędących obiektami.
weak Tworzenie kopii __weak jest syntetyzowane za pomocą __weak , więc wartość zostanie anulowana, gdy __weak obiekt zostanie zwolniony.
class Akcesoria do właściwości są syntetyzowane jako metody klasowe zamiast metod instancji. Żadne miejsce do przechowywania kopii zapasowej nie jest syntetyzowane.
nullable Właściwość przyjmuje wartości nil . Używany głównie do szybkiego mostkowania.
nonnull Właściwość nie przyjmuje wartości nil . Używany głównie do szybkiego mostkowania.
null_resettable Właściwość akceptuje wartości nil w seterze, ale nigdy nie zwraca wartości nil z gettera. Twoja niestandardowa implementacja gettera lub settera musi zapewnić takie zachowanie. Używany głównie do szybkiego mostkowania.
null_unspecified Domniemany. Ta właściwość nie określa obsługi wartości nil . Używany głównie do szybkiego mostkowania.

Jakie są właściwości?

Oto przykładowa klasa, która ma kilka zmiennych instancji, bez użycia właściwości:

@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

Jest to całkiem sporo kodu typu „płyta podstawowa” do utworzenia prostej zmiennej instancji. Musisz utworzyć zmienną instancji i stworzyć metody akcesora, które nie robią nic poza ustawieniem lub zwróceniem zmiennej instancji. Tak więc w Objective-C 2.0, Apple wprowadził właściwości, które automatycznie generują część lub całość kodu tablicy kontrolnej.

Oto powyższa klasa przepisana właściwościami:

@interface TestClass

@property NSString *someString;
@property int someInt;

@end


@implementation testClass

@end

Właściwość jest zmienną instancji połączoną z automatycznie generowanymi obiektami pobierającymi i ustawiającymi. Dla właściwość o nazwie someString , getter i setter nazywane są someString i setSomeString: odpowiednio. Nazwa zmiennej instancji jest domyślnie nazwa własności poprzedzona znakiem podkreślenia (tak zmienna instancji dla someString nazywa _someString , ale może to być pominięte z @synthesize dyrektywy w @implementation sekcji:

@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

Dostęp do właściwości można uzyskać, wywołując metody pobierające i ustawiające:

[testObject setSomeString:@"Foo"];
NSLog(@"someInt is %d", [testObject someInt]);

Można również uzyskać do nich dostęp za pomocą notacji kropkowej:

testObject.someString = @"Foo";
NSLog(@"someInt is %d", testObject.someInt);

Niestandardowe pobieracze i ustawiacze

Domyślne moduły pobierające i ustawiające właściwości można zastąpić:

@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

Może to być przydatne do zapewnienia na przykład leniwej inicjalizacji (poprzez przesłonięcie modułu pobierającego, aby ustawić wartość początkową, jeśli jeszcze nie została ustawiona):

- (NSString *)someString {
    if (_someString == nil) {
        _someString = [self getInitialValueForSomeString];
    }
    return _someString;
}

Możesz także utworzyć właściwość, która oblicza jej wartość w module pobierającym:

@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

Właściwości powodujące aktualizacje

Ten obiekt, Shape ma właściwość image , który zależy od numberOfSides i sideWidth . Jeśli którykolwiek z nich jest ustawiony, image musi zostać ponownie obliczony. Ponowne obliczenie jest jednak prawdopodobnie długie i należy je wykonać tylko raz, jeśli obie właściwości są ustawione, więc Shape zapewnia sposób ustawienia obu właściwości i ponownego obliczenia tylko raz. Odbywa się to poprzez bezpośrednie ustawienie właściwości ivars.

W 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

W 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

Gdy właściwości są przypisane do (przy użyciu object.property = value ), wywoływana jest metoda ustawiająca setProperty: object.property = value Ten seter, nawet jeśli został podany przez @synthesize , może być zmieniona, jak to jest w tym przypadku dla numberOfSides i sideWidth . Jeśli jednak ustawisz ivar właściwości bezpośrednio (poprzez property jeśli obiekt jest własny, lub object->property ), nie wywołuje on modułu pobierającego ani ustawiającego, umożliwiając wykonywanie rzeczy takich jak wiele zestawów właściwości, które wywołują tylko jedną aktualizację lub ominąć skutki uboczne wywoływane przez setera.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow