Let's say we have this CustomButton
interface:
@interface CustomButton : UIButton
@property (nonatomic, assign) CGFloat minWidth;
@end
Each time minWidth
is changed, we want to layout our CustomButton
again. As far as I know, we have two solutions:
// In -initWithFrame:
[self addObserver:self forKeyPath:@"minWidth" options:0 context:nil];
// In -observeValueForKeyPath:ofObject:change:context:
[self setNeedsLayout];
minWidth
's setter// In -setMinWidth:
_minWidth = minWidth; // Side note: it's an ARC project
[self setNeedsLayout];
Which one is the proper solution and why?
I can think of 3 reasons to override the setter rather than KVO the property.
Unless you explicitly need or want side-effects, the path of least resistance (or overhead in this case) is to override the setter. KVO involves not only a binding to the given property, but an assumption that the observer will be alive throughout the duration of the binding. Don't even get me started about how challenging KVO can be to debug, as well! The infamous "breakpoint on NSKVODeallocateBreak" would be enough to scare anyone off.
"Observing yourself", while a good idea in theory, is tougher to get right than overriding the setter. KVO is also an extra (however minimal) amount of overhead on top of setters that is only really useful for binding to other objects. Besides, if you regard a class as a self-contained unit, then it really shouldn't need to observe any properties of itself. Setters exist precisely so that a given class can choose to react to changes in its properties, or even reject or modify said changes.
By observing yourself, you've now committed to the rules of KVO: namely remembering to remove yourself as an observer, and implementing
-observeValueForKeyPath:ofObject:change:context:
.
Relative to the task at hand, this is way too much work. Why would you want to have to remember to do all of that?