導致更新的屬性

這個物件,Shape 有一個屬性 image,取決於 numberOfSidessideWidth。如果設定了其中任何一個,則必須重新計算 image。但重新計算可能很長,只需要設定兩個屬性就可以完成一次,因此 Shape 提供了一種設定兩個屬性並且只重新計算一次的方法。這是通過直接設定屬性 ivars 來完成的。

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

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

當屬性被分配給(使用 object.property = value)時,呼叫 setter 方法 setProperty:。這個 setter,即使由 @synthesize 提供,也可以被覆蓋,就像在這種情況下 numberOfSidessideWidth 一樣。但是,如果你直接設定屬性的 ivar(如果物件是 self 或 object->property,則通過 property),它不會呼叫 getter 或 setter,允許你執行多個屬性集,只呼叫一個更新或旁路側 - 設定者造成的影響。