2

In KVO I subscribe to receive change notifications from a potential sender with:

[potentialSender addObserver: self 
                  forKeyPath: NSStringFromSelector(@selector(aProperty))
                     options: 0
                     context: myKVOHandle];

And I can unsubscribe with:

[potentialSender removeObserver: self
                     forKeyPath: NSStringFromSelector(@selector(aProperty))
                        context: myKVOHandle];

Where KVO handles might be created with this c idiom.

Are calls like these counted – so every add must be directly paired to and precede a remove – this is like the pre-ARC retain and release?

Alternatively, are they idempotent – any number of add calls can be stopped by a single remove, several remove operations without a matching add are safe?


I believe the idempotent approach is used for [aControl addTarget:action:forControlEvents:] and also [aNotificationCentre addObserver:selector:name:object:]. I was wrong about notification centre addObserver calls. They are not idempotent. However, removes are. Thanks to Rob for correcting me on this.

Community
  • 1
  • 1
Benjohn
  • 13,228
  • 9
  • 65
  • 127
  • 1
    That `NSStringFromSelector(@selector(aProperty))` is kind of clever. I'd never seen that before, but it's an interesting way to avoid at least certain kinds of typos. – Rob Napier Apr 09 '15 at 18:12
  • Same here - never occured to me that we could also use it for property accessors. Sweet! – cacau Apr 10 '15 at 05:43
  • @RobNapier Thanks! It gives some compile time safety and is also "refactor proof" for a rename. It is annoyingly verbose though. – Benjohn Apr 10 '15 at 10:17

1 Answers1

3

KVO calls must be balanced. Every addObserver:... must be balanced with an equivalent removeObserver:.... And there is no mechanism to "unsubscribe all" like there is for NSNotificationCenter. A remove that does not balance an add is an error. KVO is very picky.

Note that NSNotificationCenter is absolutely not idempotent. Multiple, identical addObserver:... calls will result in multiple notifications. It's just possible to do a global removeObserver:self without balancing every addObserver:..., and it is safe to remove when you have not added.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Super – thanks for answer and for clearing me up on notifications too – so, `removeObserver: self` is idempotent, but add isn't? – Benjohn Apr 09 '15 at 18:33
  • 1
    Correct. In any object that uses NSNotificationCenter, I always add an extra removeObserver:self in dealloc, just as insurance. – Rob Napier Apr 09 '15 at 18:51