Reputation: 15365
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?
Upvotes: 6
Views: 599
Reputation: 5665
The correct answer is actually in your question:
Each time minWidth is changed, we want to layout our CustomButton again.
There are no absolute answers in programming, which is what makes it as much an art as a science. There are some strategies you can adopt however to ensure the act of programming does not get in the way of what you are trying to achieve or create. Programming itself is a means to an end.
It follows therefore that your code should be as complex as it needs to be, but no more.
While you could use key-value pair observing, and no one could fault you, a better approach (in the context of your question) would be to override the setter, as this is your intention (quoted above) in it's simplest, most concise and literal form.
At the zoomed-in level, your code should be as easy to read and parse as possible, so that these simple blocks can be assembled into more complex structures. If at the most zoomed-in detail code is needlessly verbose or complicated, this will manifest as friction to the project as a whole (harder to debug, more prone to error, and so forth).
Upvotes: 0
Reputation: 43330
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?
Upvotes: 5