Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it better to observe properties or override setters?

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:

Observing property's value

// In -initWithFrame:
[self addObserver:self forKeyPath:@"minWidth" options:0 context:nil];

// In -observeValueForKeyPath:ofObject:change:context:
[self setNeedsLayout];

Overriding minWidth's setter

// In -setMinWidth:
_minWidth = minWidth; // Side note: it's an ARC project
[self setNeedsLayout];

Which one is the proper solution and why?

like image 458
ldiqual Avatar asked Mar 20 '13 22:03

ldiqual


1 Answers

I can think of 3 reasons to override the setter rather than KVO the property.

1: Side-Effects may vary

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.

2: Conventional Wisdom

"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.

3: We're all lazy

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?

like image 72
CodaFi Avatar answered Oct 04 '22 22:10

CodaFi