This object, Shape
has a property image
that depends on numberOfSides
and sideWidth
. If either one of them is set, than the image
has to be recalculated. But recalculation is presumably long, and only needs to be done once if both properties are set, so the Shape
provides a way to set both properties and only recalculate once. This is done by setting the property ivars directly.
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
When properties are assigned to (using object.property = value
), the setter method setProperty:
is called. This setter, even if provided by @synthesize
, can be overridden, as it is in this case for numberOfSides
and sideWidth
. However, if you set an property's ivar directly (through property
if the object is self, or object->property
), it doesn't call the getter or setter, allowing you to do things like multiple property sets that only call one update or bypass side-effects caused by the setter.