Search code examples
cocoacocoa-touchkey-value-observing

KVO's add & remove observer methods – counted or idempotent?


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.


Solution

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