Defects of KVO

KVO(Key-Value Observing) is a very nice programming facility from Apple. Working together with KVC(Key-Value Coding), it makes the life of Apple developers a lot easier and happier.

However, I recently found some annoying problems of KVO while building some reusable programming components for Voodo and future iOS projects.

Observers can not be queried

Observers are stored in dictionaries1, so it should be very easy to query whether an object A is a registered observer of object B. But one can’t do that.

Unregistering an unregistered observer throws exception

One can not query whether A is an observer of B in the first place, and can neither try to unregister it from B when one wants to ensure that A is unregistered from B. It is just ridiculous! And why is removing a nonexistent observer so fatal while removing a nonexistent entry from a collection is reasonably ignored?2

Observers/observees don’t auto-dissolve the KVO relationship in dealloc

It can be easily done in KVO framework code since it already has the data structure keeping the observer-observee relationship information, and is very reasonable things to do – when any part of a relationship is gone the relationship is ended. Without the auto-unregistration, developers’ responsibility is unnecessarily heavier. In fact, it is no easy work in cases where observers outlive observees, because an observee needs to notify its observers of its death so the observers can detach themselves from the dying observee.3

All in all

KVO leaves some extra, tedious, and burdensome relationship management work to us while it could be easily and efficiently done at the root of itself.4

The KVO relationship management is especially stressful for observers watching many dynamic observees which is not unusual for generic components – UINavigationController and UITabBarController both manage a dynamic group of UIViewControllers and may observe some properties of them. It is even worse in my component because not only the observee but also the observed properties of them are dynamic.

  1. See NSKeyValueObserving protocol’s observationInfo

  2. See NSMutableArray’s removeObject: and NSMutableDictionary’s removeObjectForKey:

  3. Normally it is the observers that are doing the KVO relationship management and it is the job of whoever did the connection to do the disconnection, but vice versa. 

  4. Well, as Appler eskimo1 said in devforums, it is harder than one might think because KVO needs to be both thread safe and GC clean, and must be careful to not impact the performance of code that isn’t using it